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, MonoError *error);
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);
429 * @image: a MonoImage
432 * If @image is NULL, free @ptr, otherwise do nothing.
435 image_g_free (MonoImage *image, gpointer ptr)
441 #ifndef DISABLE_REFLECTION_EMIT
443 image_strdup (MonoImage *image, const char *s)
445 MONO_REQ_GC_NEUTRAL_MODE;
448 return mono_image_strdup (image, s);
454 #define image_g_new(image,struct_type, n_structs) \
455 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
457 #define image_g_new0(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
462 alloc_table (MonoDynamicTable *table, guint nrows)
464 MONO_REQ_GC_NEUTRAL_MODE;
467 g_assert (table->columns);
468 if (nrows + 1 >= table->alloc_rows) {
469 while (nrows + 1 >= table->alloc_rows) {
470 if (table->alloc_rows == 0)
471 table->alloc_rows = 16;
473 table->alloc_rows *= 2;
476 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
481 make_room_in_stream (MonoDynamicStream *stream, int size)
483 MONO_REQ_GC_NEUTRAL_MODE;
485 if (size <= stream->alloc_size)
488 while (stream->alloc_size <= size) {
489 if (stream->alloc_size < 4096)
490 stream->alloc_size = 4096;
492 stream->alloc_size *= 2;
495 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
501 MONO_REQ_GC_NEUTRAL_MODE;
505 gpointer oldkey, oldval;
507 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508 return GPOINTER_TO_UINT (oldval);
510 len = strlen (str) + 1;
513 make_room_in_stream (sh, idx + len);
516 * We strdup the string even if we already copy them in sh->data
517 * so that the string pointers in the hash remain valid even if
518 * we need to realloc sh->data. We may want to avoid that later.
520 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521 memcpy (sh->data + idx, str, len);
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
529 MONO_REQ_GC_UNSAFE_MODE;
531 char *name = mono_string_to_utf8 (str);
533 idx = string_heap_insert (sh, name);
538 #ifndef DISABLE_REFLECTION_EMIT
540 string_heap_init (MonoDynamicStream *sh)
542 MONO_REQ_GC_NEUTRAL_MODE;
545 sh->alloc_size = 4096;
546 sh->data = (char *)g_malloc (4096);
547 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548 string_heap_insert (sh, "");
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
555 MONO_REQ_GC_NEUTRAL_MODE;
559 make_room_in_stream (stream, stream->index + len);
560 memcpy (stream->data + stream->index, data, len);
562 stream->index += len;
564 * align index? Not without adding an additional param that controls it since
565 * we may store a blob value in pieces.
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
573 MONO_REQ_GC_NEUTRAL_MODE;
577 make_room_in_stream (stream, stream->index + len);
578 memset (stream->data + stream->index, 0, len);
580 stream->index += len;
585 stream_data_align (MonoDynamicStream *stream)
587 MONO_REQ_GC_NEUTRAL_MODE;
590 guint32 count = stream->index % 4;
592 /* we assume the stream data will be aligned */
594 mono_image_add_stream_data (stream, buf, 4 - count);
597 #ifndef DISABLE_REFLECTION_EMIT
599 mono_blob_entry_hash (const char* str)
601 MONO_REQ_GC_NEUTRAL_MODE;
605 len = mono_metadata_decode_blob_size (str, &str);
609 for (str += 1; str < end; str++)
610 h = (h << 5) - h + *str;
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619 MONO_REQ_GC_NEUTRAL_MODE;
624 len = mono_metadata_decode_blob_size (str1, &end1);
625 len2 = mono_metadata_decode_blob_size (str2, &end2);
628 return memcmp (end1, end2, len) == 0;
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
634 MONO_REQ_GC_NEUTRAL_MODE;
638 gpointer oldkey, oldval;
640 copy = (char *)g_malloc (s1+s2);
641 memcpy (copy, b1, s1);
642 memcpy (copy + s1, b2, s2);
643 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
645 idx = GPOINTER_TO_UINT (oldval);
647 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648 mono_image_add_stream_data (&assembly->blob, b2, s2);
649 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
657 MONO_REQ_GC_NEUTRAL_MODE;
661 guint32 size = buf->p - buf->buf;
663 g_assert (size <= (buf->end - buf->buf));
664 mono_metadata_encode_value (size, b, &b);
665 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
669 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670 * dest may be misaligned.
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674 MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
678 for (elem = 0; elem < nelem; ++elem) {
704 g_assert_not_reached ();
710 memcpy (dest, val, len * nelem);
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
717 MONO_REQ_GC_UNSAFE_MODE;
721 guint32 idx = 0, len;
723 len = str->length * 2;
724 mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
727 char *swapped = g_malloc (2 * mono_string_length (str));
728 const char *p = (const char*)mono_string_chars (str);
730 swap_with_size (swapped, p, 2, mono_string_length (str));
731 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
735 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
740 #ifndef DISABLE_REFLECTION_EMIT
742 default_class_from_mono_type (MonoType *type)
744 MONO_REQ_GC_NEUTRAL_MODE;
746 switch (type->type) {
747 case MONO_TYPE_OBJECT:
748 return mono_defaults.object_class;
750 return mono_defaults.void_class;
751 case MONO_TYPE_BOOLEAN:
752 return mono_defaults.boolean_class;
754 return mono_defaults.char_class;
756 return mono_defaults.sbyte_class;
758 return mono_defaults.byte_class;
760 return mono_defaults.int16_class;
762 return mono_defaults.uint16_class;
764 return mono_defaults.int32_class;
766 return mono_defaults.uint32_class;
768 return mono_defaults.int_class;
770 return mono_defaults.uint_class;
772 return mono_defaults.int64_class;
774 return mono_defaults.uint64_class;
776 return mono_defaults.single_class;
778 return mono_defaults.double_class;
779 case MONO_TYPE_STRING:
780 return mono_defaults.string_class;
782 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783 g_assert_not_reached ();
791 * mono_class_get_ref_info:
793 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
796 mono_class_get_ref_info (MonoClass *klass)
798 MONO_REQ_GC_UNSAFE_MODE;
800 if (klass->ref_info_handle == 0)
803 return mono_gchandle_get_target (klass->ref_info_handle);
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
809 MONO_REQ_GC_UNSAFE_MODE;
811 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812 g_assert (klass->ref_info_handle != 0);
816 mono_class_free_ref_info (MonoClass *klass)
818 MONO_REQ_GC_NEUTRAL_MODE;
820 if (klass->ref_info_handle) {
821 mono_gchandle_free (klass->ref_info_handle);
822 klass->ref_info_handle = 0;
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
829 MONO_REQ_GC_NEUTRAL_MODE;
832 MonoGenericInst *class_inst;
837 class_inst = gclass->context.class_inst;
839 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840 klass = gclass->container_class;
841 sigbuffer_add_value (buf, klass->byval_arg.type);
842 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
844 sigbuffer_add_value (buf, class_inst->type_argc);
845 for (i = 0; i < class_inst->type_argc; ++i)
846 encode_type (assembly, class_inst->type_argv [i], buf);
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
853 MONO_REQ_GC_NEUTRAL_MODE;
856 g_assert_not_reached ();
861 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
865 case MONO_TYPE_BOOLEAN:
879 case MONO_TYPE_STRING:
880 case MONO_TYPE_OBJECT:
881 case MONO_TYPE_TYPEDBYREF:
882 sigbuffer_add_value (buf, type->type);
885 sigbuffer_add_value (buf, type->type);
886 encode_type (assembly, type->data.type, buf);
888 case MONO_TYPE_SZARRAY:
889 sigbuffer_add_value (buf, type->type);
890 encode_type (assembly, &type->data.klass->byval_arg, buf);
892 case MONO_TYPE_VALUETYPE:
893 case MONO_TYPE_CLASS: {
894 MonoClass *k = mono_class_from_mono_type (type);
896 if (k->generic_container) {
897 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898 encode_generic_class (assembly, gclass, buf);
901 * Make sure we use the correct type.
903 sigbuffer_add_value (buf, k->byval_arg.type);
905 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906 * otherwise two typerefs could point to the same type, leading to
907 * verification errors.
909 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
913 case MONO_TYPE_ARRAY:
914 sigbuffer_add_value (buf, type->type);
915 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916 sigbuffer_add_value (buf, type->data.array->rank);
917 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918 sigbuffer_add_value (buf, 0);
920 case MONO_TYPE_GENERICINST:
921 encode_generic_class (assembly, type->data.generic_class, buf);
925 sigbuffer_add_value (buf, type->type);
926 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
929 g_error ("need to encode type %x", type->type);
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
936 MONO_REQ_GC_UNSAFE_MODE;
938 mono_error_init (error);
941 sigbuffer_add_value (buf, MONO_TYPE_VOID);
945 MonoType *t = mono_reflection_type_get_handle (type, error);
946 return_if_nok (error);
947 encode_type (assembly, t, buf);
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
953 MONO_REQ_GC_UNSAFE_MODE;
957 mono_error_init (error);
960 for (i = 0; i < mono_array_length (modreq); ++i) {
961 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962 return_if_nok (error);
963 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
968 for (i = 0; i < mono_array_length (modopt); ++i) {
969 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970 return_if_nok (error);
971 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
977 #ifndef DISABLE_REFLECTION_EMIT
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
981 MONO_REQ_GC_UNSAFE_MODE;
985 guint32 nparams = sig->param_count;
991 sigbuffer_init (&buf, 32);
993 * FIXME: vararg, explicit_this, differenc call_conv values...
995 idx = sig->call_convention;
997 idx |= 0x20; /* hasthis */
998 if (sig->generic_param_count)
999 idx |= 0x10; /* generic */
1000 sigbuffer_add_byte (&buf, idx);
1001 if (sig->generic_param_count)
1002 sigbuffer_add_value (&buf, sig->generic_param_count);
1003 sigbuffer_add_value (&buf, nparams);
1004 encode_type (assembly, sig->ret, &buf);
1005 for (i = 0; i < nparams; ++i) {
1006 if (i == sig->sentinelpos)
1007 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008 encode_type (assembly, sig->params [i], &buf);
1010 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011 sigbuffer_free (&buf);
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1019 MONO_REQ_GC_UNSAFE_MODE;
1021 mono_error_init (error);
1024 * FIXME: reuse code from method_encode_signature().
1028 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1029 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1033 sigbuffer_init (&buf, 32);
1034 /* LAMESPEC: all the call conv spec is foobared */
1035 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036 if (mb->call_conv & 2)
1037 idx |= 0x5; /* vararg */
1038 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039 idx |= 0x20; /* hasthis */
1041 idx |= 0x10; /* generic */
1042 sigbuffer_add_byte (&buf, idx);
1044 sigbuffer_add_value (&buf, ngparams);
1045 sigbuffer_add_value (&buf, nparams + notypes);
1046 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1049 encode_reflection_type (assembly, mb->rtype, &buf, error);
1052 for (i = 0; i < nparams; ++i) {
1053 MonoArray *modreq = NULL;
1054 MonoArray *modopt = NULL;
1055 MonoReflectionType *pt;
1057 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1064 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065 encode_reflection_type (assembly, pt, &buf, error);
1070 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071 for (i = 0; i < notypes; ++i) {
1072 MonoReflectionType *pt;
1074 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075 encode_reflection_type (assembly, pt, &buf, error);
1080 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1082 sigbuffer_free (&buf);
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1089 MONO_REQ_GC_UNSAFE_MODE;
1091 mono_error_init (error);
1093 MonoDynamicTable *table;
1095 guint32 idx, sig_idx;
1096 guint nl = mono_array_length (ilgen->locals);
1100 sigbuffer_init (&buf, 32);
1101 sigbuffer_add_value (&buf, 0x07);
1102 sigbuffer_add_value (&buf, nl);
1103 for (i = 0; i < nl; ++i) {
1104 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1107 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1109 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110 if (!is_ok (error)) {
1111 sigbuffer_free (&buf);
1115 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116 sigbuffer_free (&buf);
1118 if (assembly->standalonesig_cache == NULL)
1119 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1124 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125 idx = table->next_idx ++;
1127 alloc_table (table, table->rows);
1128 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1130 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1132 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1140 MONO_REQ_GC_UNSAFE_MODE;
1142 guint32 num_clauses = 0;
1145 MonoILExceptionInfo *ex_info;
1146 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148 if (ex_info->handlers)
1149 num_clauses += mono_array_length (ex_info->handlers);
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1161 MONO_REQ_GC_UNSAFE_MODE;
1163 mono_error_init (error);
1165 MonoExceptionClause *clauses;
1166 MonoExceptionClause *clause;
1167 MonoILExceptionInfo *ex_info;
1168 MonoILExceptionBlock *ex_block;
1169 guint32 finally_start;
1170 int i, j, clause_index;;
1172 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1175 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177 finally_start = ex_info->start + ex_info->len;
1178 if (!ex_info->handlers)
1180 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182 clause = &(clauses [clause_index]);
1184 clause->flags = ex_block->type;
1185 clause->try_offset = ex_info->start;
1187 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188 clause->try_len = finally_start - ex_info->start;
1190 clause->try_len = ex_info->len;
1191 clause->handler_offset = ex_block->start;
1192 clause->handler_len = ex_block->len;
1193 if (ex_block->extype) {
1194 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1196 if (!is_ok (error)) {
1197 image_g_free (image, clauses);
1200 clause->data.catch_class = mono_class_from_mono_type (extype);
1202 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203 clause->data.filter_offset = ex_block->filter_offset;
1205 clause->data.filter_offset = 0;
1207 finally_start = ex_block->start + ex_block->len;
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1218 * method_encode_code:
1220 * @assembly the assembly
1221 * @mb the managed MethodBuilder
1222 * @error set on error
1224 * Note that the return value is not sensible if @error is set.
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1229 MONO_REQ_GC_UNSAFE_MODE;
1234 gint32 max_stack, i;
1235 gint32 num_locals = 0;
1236 gint32 num_exception = 0;
1239 char fat_header [12];
1241 guint16 short_value;
1242 guint32 local_sig = 0;
1243 guint32 header_size = 12;
1246 mono_error_init (error);
1248 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1253 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1255 code = mb->ilgen->code;
1256 code_size = mb->ilgen->code_len;
1257 max_stack = mb->ilgen->max_stack;
1258 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259 if (mb->ilgen->ex_handlers)
1260 num_exception = method_count_clauses (mb->ilgen);
1264 char *name = mono_string_to_utf8 (mb->name);
1265 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1272 code_size = mono_array_length (code);
1273 max_stack = 8; /* we probably need to run a verifier on the code... */
1276 stream_data_align (&assembly->code);
1278 /* check for exceptions, maxstack, locals */
1279 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1281 if (code_size < 64 && !(code_size & 1)) {
1282 flags = (code_size << 2) | 0x2;
1283 } else if (code_size < 32 && (code_size & 1)) {
1284 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1288 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289 /* add to the fixup todo list */
1290 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293 return assembly->text_rva + idx;
1297 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298 return_val_if_nok (error, 0);
1301 * FIXME: need to set also the header size in fat_flags.
1302 * (and more sects and init locals flags)
1306 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307 if (mb->init_locals)
1308 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309 fat_header [0] = fat_flags;
1310 fat_header [1] = (header_size / 4 ) << 4;
1311 short_value = GUINT16_TO_LE (max_stack);
1312 memcpy (fat_header + 2, &short_value, 2);
1313 int_value = GUINT32_TO_LE (code_size);
1314 memcpy (fat_header + 4, &int_value, 4);
1315 int_value = GUINT32_TO_LE (local_sig);
1316 memcpy (fat_header + 8, &int_value, 4);
1317 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318 /* add to the fixup todo list */
1319 if (mb->ilgen && mb->ilgen->num_token_fixups)
1320 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1322 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323 if (num_exception) {
1324 unsigned char sheader [4];
1325 MonoILExceptionInfo * ex_info;
1326 MonoILExceptionBlock * ex_block;
1329 stream_data_align (&assembly->code);
1330 /* always use fat format for now */
1331 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332 num_exception *= 6 * sizeof (guint32);
1333 num_exception += 4; /* include the size of the header */
1334 sheader [1] = num_exception & 0xff;
1335 sheader [2] = (num_exception >> 8) & 0xff;
1336 sheader [3] = (num_exception >> 16) & 0xff;
1337 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338 /* fat header, so we are already aligned */
1340 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342 if (ex_info->handlers) {
1343 int finally_start = ex_info->start + ex_info->len;
1344 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1346 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1348 val = GUINT32_TO_LE (ex_block->type);
1349 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1351 val = GUINT32_TO_LE (ex_info->start);
1352 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353 /* need fault, too, probably */
1354 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355 val = GUINT32_TO_LE (finally_start - ex_info->start);
1357 val = GUINT32_TO_LE (ex_info->len);
1358 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359 /* handler offset */
1360 val = GUINT32_TO_LE (ex_block->start);
1361 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1363 val = GUINT32_TO_LE (ex_block->len);
1364 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365 finally_start = ex_block->start + ex_block->len;
1366 if (ex_block->extype) {
1367 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368 return_val_if_nok (error, 0);
1370 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1372 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373 val = ex_block->filter_offset;
1377 val = GUINT32_TO_LE (val);
1378 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379 /*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",
1380 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);*/
1383 g_error ("No clauses for ex info block %d", i);
1387 return assembly->text_rva + idx;
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1393 MONO_REQ_GC_NEUTRAL_MODE;
1396 MonoDynamicTable *table;
1399 table = &assembly->tables [table_idx];
1401 g_assert (col < table->columns);
1403 values = table->values + table->columns;
1404 for (i = 1; i <= table->rows; ++i) {
1405 if (values [col] == token)
1407 values += table->columns;
1413 * LOCKING: Acquires the loader lock.
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1418 MONO_REQ_GC_NEUTRAL_MODE;
1420 MonoCustomAttrInfo* res;
1422 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1427 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1435 MONO_REQ_GC_UNSAFE_MODE;
1437 /* FIXME: Need to do more checks */
1438 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1441 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1451 MONO_REQ_GC_UNSAFE_MODE;
1453 int i, index, count, not_visible;
1454 MonoCustomAttrInfo *ainfo;
1455 MonoReflectionCustomAttr *cattr;
1459 /* FIXME: check in assembly the Run flag is set */
1461 count = mono_array_length (cattrs);
1463 /* Skip nonpublic attributes since MS.NET seems to do the same */
1464 /* FIXME: This needs to be done more globally */
1466 for (i = 0; i < count; ++i) {
1467 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468 if (!custom_attr_visible (image, cattr))
1471 count -= not_visible;
1473 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1475 ainfo->image = image;
1476 ainfo->num_attrs = count;
1477 ainfo->cached = alloc_img != NULL;
1479 for (i = 0; i < count; ++i) {
1480 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481 if (custom_attr_visible (image, cattr)) {
1482 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484 ainfo->attrs [index].ctor = cattr->ctor->method;
1485 ainfo->attrs [index].data = saved;
1486 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1494 #ifndef DISABLE_REFLECTION_EMIT
1496 * LOCKING: Acquires the loader lock.
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1501 MONO_REQ_GC_UNSAFE_MODE;
1503 MonoCustomAttrInfo *ainfo, *tmp;
1505 if (!cattrs || !mono_array_length (cattrs))
1508 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1510 mono_loader_lock ();
1511 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1513 mono_custom_attrs_free (tmp);
1514 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515 mono_loader_unlock ();
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1523 MONO_REQ_GC_NEUTRAL_MODE;
1525 if (ainfo && !ainfo->cached)
1530 * idx is the table index of the object
1531 * type is one of MONO_CUSTOM_ATTR_*
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1536 MONO_REQ_GC_UNSAFE_MODE;
1538 MonoDynamicTable *table;
1539 MonoReflectionCustomAttr *cattr;
1541 guint32 count, i, token;
1543 char *p = blob_size;
1545 mono_error_init (error);
1547 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1550 count = mono_array_length (cattrs);
1551 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552 table->rows += count;
1553 alloc_table (table, table->rows);
1554 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555 idx <<= MONO_CUSTOM_ATTR_BITS;
1557 for (i = 0; i < count; ++i) {
1558 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561 if (!mono_error_ok (error)) goto fail;
1562 type = mono_metadata_token_index (token);
1563 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564 switch (mono_metadata_token_table (token)) {
1565 case MONO_TABLE_METHOD:
1566 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1568 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569 * method, not the one returned by mono_image_create_token ().
1571 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1573 case MONO_TABLE_MEMBERREF:
1574 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1577 g_warning ("got wrong token in custom attr");
1580 values [MONO_CUSTOM_ATTR_TYPE] = type;
1582 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585 values += MONO_CUSTOM_ATTR_SIZE;
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1598 MONO_REQ_GC_UNSAFE_MODE;
1600 MonoDynamicTable *table;
1602 guint32 count, i, idx;
1603 MonoReflectionPermissionSet *perm;
1608 count = mono_array_length (permissions);
1609 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610 table->rows += count;
1611 alloc_table (table, table->rows);
1613 for (i = 0; i < mono_array_length (permissions); ++i) {
1614 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1616 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1618 idx = mono_metadata_token_index (parent_token);
1619 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620 switch (mono_metadata_token_table (parent_token)) {
1621 case MONO_TABLE_TYPEDEF:
1622 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1624 case MONO_TABLE_METHOD:
1625 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1627 case MONO_TABLE_ASSEMBLY:
1628 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1631 g_assert_not_reached ();
1634 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635 values [MONO_DECL_SECURITY_PARENT] = idx;
1636 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1643 * Fill in the MethodDef and ParamDef tables for a method.
1644 * This is used for both normal methods and constructors.
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1649 MONO_REQ_GC_UNSAFE_MODE;
1651 MonoDynamicTable *table;
1655 mono_error_init (error);
1657 /* room in this table is already allocated */
1658 table = &assembly->tables [MONO_TABLE_METHOD];
1659 *mb->table_idx = table->next_idx ++;
1660 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663 values [MONO_METHOD_FLAGS] = mb->attrs;
1664 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666 return_val_if_nok (error, FALSE);
1667 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668 return_val_if_nok (error, FALSE);
1670 table = &assembly->tables [MONO_TABLE_PARAM];
1671 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1673 mono_image_add_decl_security (assembly,
1674 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1677 MonoDynamicTable *mtable;
1680 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1684 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685 if (mono_array_get (mb->pinfo, gpointer, i))
1688 table->rows += count;
1689 alloc_table (table, table->rows);
1690 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692 MonoReflectionParamBuilder *pb;
1693 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694 values [MONO_PARAM_FLAGS] = pb->attrs;
1695 values [MONO_PARAM_SEQUENCE] = i;
1696 if (pb->name != NULL) {
1697 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1699 values [MONO_PARAM_NAME] = 0;
1701 values += MONO_PARAM_SIZE;
1702 if (pb->marshal_info) {
1704 alloc_table (mtable, mtable->rows);
1705 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708 return_val_if_nok (error, FALSE);
1710 pb->table_idx = table->next_idx++;
1711 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712 guint32 field_type = 0;
1713 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1715 alloc_table (mtable, mtable->rows);
1716 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719 mvalues [MONO_CONSTANT_TYPE] = field_type;
1720 mvalues [MONO_CONSTANT_PADDING] = 0;
1729 #ifndef DISABLE_REFLECTION_EMIT
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1733 MONO_REQ_GC_UNSAFE_MODE;
1735 mono_error_init (error);
1736 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1738 rmb->ilgen = mb->ilgen;
1739 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740 return_val_if_nok (error, FALSE);
1741 rmb->parameters = mb->parameters;
1742 rmb->generic_params = mb->generic_params;
1743 rmb->generic_container = mb->generic_container;
1744 rmb->opt_types = NULL;
1745 rmb->pinfo = mb->pinfo;
1746 rmb->attrs = mb->attrs;
1747 rmb->iattrs = mb->iattrs;
1748 rmb->call_conv = mb->call_conv;
1749 rmb->code = mb->code;
1750 rmb->type = mb->type;
1751 rmb->name = mb->name;
1752 rmb->table_idx = &mb->table_idx;
1753 rmb->init_locals = mb->init_locals;
1754 rmb->skip_visibility = FALSE;
1755 rmb->return_modreq = mb->return_modreq;
1756 rmb->return_modopt = mb->return_modopt;
1757 rmb->param_modreq = mb->param_modreq;
1758 rmb->param_modopt = mb->param_modopt;
1759 rmb->permissions = mb->permissions;
1760 rmb->mhandle = mb->mhandle;
1765 rmb->charset = mb->charset;
1766 rmb->extra_flags = mb->extra_flags;
1767 rmb->native_cc = mb->native_cc;
1768 rmb->dllentry = mb->dllentry;
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1778 MONO_REQ_GC_UNSAFE_MODE;
1780 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1782 mono_error_init (error);
1784 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1786 rmb->ilgen = mb->ilgen;
1787 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788 return_val_if_nok (error, FALSE);
1789 rmb->parameters = mb->parameters;
1790 rmb->generic_params = NULL;
1791 rmb->generic_container = NULL;
1792 rmb->opt_types = NULL;
1793 rmb->pinfo = mb->pinfo;
1794 rmb->attrs = mb->attrs;
1795 rmb->iattrs = mb->iattrs;
1796 rmb->call_conv = mb->call_conv;
1798 rmb->type = mb->type;
1799 rmb->name = mono_string_new (mono_domain_get (), name);
1800 rmb->table_idx = &mb->table_idx;
1801 rmb->init_locals = mb->init_locals;
1802 rmb->skip_visibility = FALSE;
1803 rmb->return_modreq = NULL;
1804 rmb->return_modopt = NULL;
1805 rmb->param_modreq = mb->param_modreq;
1806 rmb->param_modopt = mb->param_modopt;
1807 rmb->permissions = mb->permissions;
1808 rmb->mhandle = mb->mhandle;
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1818 MONO_REQ_GC_UNSAFE_MODE;
1820 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1822 rmb->ilgen = mb->ilgen;
1823 rmb->rtype = mb->rtype;
1824 rmb->parameters = mb->parameters;
1825 rmb->generic_params = NULL;
1826 rmb->generic_container = NULL;
1827 rmb->opt_types = NULL;
1829 rmb->attrs = mb->attrs;
1831 rmb->call_conv = mb->call_conv;
1833 rmb->type = (MonoObject *) mb->owner;
1834 rmb->name = mb->name;
1835 rmb->table_idx = NULL;
1836 rmb->init_locals = mb->init_locals;
1837 rmb->skip_visibility = mb->skip_visibility;
1838 rmb->return_modreq = NULL;
1839 rmb->return_modopt = NULL;
1840 rmb->param_modreq = NULL;
1841 rmb->param_modopt = NULL;
1842 rmb->permissions = NULL;
1843 rmb->mhandle = mb->mhandle;
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1852 MONO_REQ_GC_UNSAFE_MODE;
1854 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855 MonoDynamicTable *table;
1858 MonoReflectionMethod *m;
1861 mono_error_init (error);
1863 if (!mb->override_methods)
1866 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1869 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1871 alloc_table (table, table->rows);
1872 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1876 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877 return_val_if_nok (error, FALSE);
1879 switch (mono_metadata_token_table (tok)) {
1880 case MONO_TABLE_MEMBERREF:
1881 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1883 case MONO_TABLE_METHOD:
1884 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1887 g_assert_not_reached ();
1889 values [MONO_METHODIMPL_DECLARATION] = tok;
1895 #ifndef DISABLE_REFLECTION_EMIT
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1899 MONO_REQ_GC_UNSAFE_MODE;
1901 MonoDynamicTable *table;
1903 ReflectionMethodBuilder rmb;
1906 mono_error_init (error);
1908 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909 !mono_image_basic_method (&rmb, assembly, error))
1912 mb->table_idx = *rmb.table_idx;
1914 if (mb->dll) { /* It's a P/Invoke method */
1916 /* map CharSet values to on-disk values */
1917 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918 int extra_flags = mb->extra_flags;
1919 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1921 alloc_table (table, table->rows);
1922 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1924 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1927 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1929 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932 table = &assembly->tables [MONO_TABLE_MODULEREF];
1934 alloc_table (table, table->rows);
1935 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936 values [MONO_IMPLMAP_SCOPE] = table->rows;
1940 if (mb->generic_params) {
1941 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942 table->rows += mono_array_length (mb->generic_params);
1943 alloc_table (table, table->rows);
1944 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1947 mono_image_get_generic_param_info (
1948 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1958 MONO_REQ_GC_UNSAFE_MODE;
1960 ReflectionMethodBuilder rmb;
1962 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1965 if (!mono_image_basic_method (&rmb, assembly, error))
1968 mb->table_idx = *rmb.table_idx;
1975 type_get_fully_qualified_name (MonoType *type)
1977 MONO_REQ_GC_NEUTRAL_MODE;
1979 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1985 MONO_REQ_GC_UNSAFE_MODE;
1990 klass = mono_class_from_mono_type (type);
1992 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993 ta = klass->image->assembly;
1994 if (assembly_is_dynamic (ta) || (ta == ass)) {
1995 if (klass->generic_class || klass->generic_container)
1996 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1999 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2010 MONO_REQ_GC_NEUTRAL_MODE;
2013 guint32 idx, i, token;
2015 if (!assembly->save)
2018 sigbuffer_init (&buf, 32);
2020 sigbuffer_add_value (&buf, 0x06);
2021 /* encode custom attributes before the type */
2022 if (type->num_mods) {
2023 for (i = 0; i < type->num_mods; ++i) {
2026 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2029 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2031 token = type->modifiers [i].token;
2034 if (type->modifiers [i].required)
2035 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2037 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2039 sigbuffer_add_value (&buf, token);
2042 encode_type (assembly, type, &buf);
2043 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044 sigbuffer_free (&buf);
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2052 MONO_REQ_GC_UNSAFE_MODE;
2054 mono_error_init (error);
2058 guint32 typespec = 0;
2062 init_type_builder_generics (fb->type);
2064 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065 return_val_if_nok (error, 0);
2066 klass = mono_class_from_mono_type (type);
2068 sigbuffer_init (&buf, 32);
2070 sigbuffer_add_value (&buf, 0x06);
2071 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2074 /* encode custom attributes before the type */
2076 if (klass->generic_container)
2077 typespec = create_typespec (assembly, type);
2080 MonoGenericClass *gclass;
2081 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082 encode_generic_class (assembly, gclass, &buf);
2084 encode_type (assembly, type, &buf);
2086 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087 sigbuffer_free (&buf);
2090 sigbuffer_free (&buf);
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2097 MONO_REQ_GC_UNSAFE_MODE;
2099 char blob_size [64];
2100 char *b = blob_size;
2103 guint32 idx = 0, len = 0, dummy = 0;
2105 buf = (char *)g_malloc (64);
2107 *ret_type = MONO_TYPE_CLASS;
2109 box_val = (char*)&dummy;
2111 box_val = ((char*)val) + sizeof (MonoObject);
2112 *ret_type = val->vtable->klass->byval_arg.type;
2115 switch (*ret_type) {
2116 case MONO_TYPE_BOOLEAN:
2121 case MONO_TYPE_CHAR:
2138 case MONO_TYPE_VALUETYPE: {
2139 MonoClass *klass = val->vtable->klass;
2141 if (klass->enumtype) {
2142 *ret_type = mono_class_enum_basetype (klass)->type;
2144 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2147 g_error ("we can't encode valuetypes, we should have never reached this line");
2150 case MONO_TYPE_CLASS:
2152 case MONO_TYPE_STRING: {
2153 MonoString *str = (MonoString*)val;
2154 /* there is no signature */
2155 len = str->length * 2;
2156 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2159 char *swapped = g_malloc (2 * mono_string_length (str));
2160 const char *p = (const char*)mono_string_chars (str);
2162 swap_with_size (swapped, p, 2, mono_string_length (str));
2163 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2173 case MONO_TYPE_GENERICINST:
2174 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2177 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2180 /* there is no signature */
2181 mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184 swap_with_size (blob_size, box_val, len, 1);
2185 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2187 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2197 MONO_REQ_GC_UNSAFE_MODE;
2199 mono_error_init (error);
2205 sigbuffer_init (&buf, 32);
2207 sigbuffer_add_value (&buf, minfo->type);
2209 switch (minfo->type) {
2210 case MONO_NATIVE_BYVALTSTR:
2211 case MONO_NATIVE_BYVALARRAY:
2212 sigbuffer_add_value (&buf, minfo->count);
2214 case MONO_NATIVE_LPARRAY:
2215 if (minfo->eltype || minfo->has_size) {
2216 sigbuffer_add_value (&buf, minfo->eltype);
2217 if (minfo->has_size) {
2218 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2221 /* LAMESPEC: ElemMult is undocumented */
2222 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2226 case MONO_NATIVE_SAFEARRAY:
2228 sigbuffer_add_value (&buf, minfo->eltype);
2230 case MONO_NATIVE_CUSTOM:
2232 str = mono_string_to_utf8 (minfo->guid);
2234 sigbuffer_add_value (&buf, len);
2235 sigbuffer_add_mem (&buf, str, len);
2238 sigbuffer_add_value (&buf, 0);
2240 /* native type name */
2241 sigbuffer_add_value (&buf, 0);
2242 /* custom marshaler type name */
2243 if (minfo->marshaltype || minfo->marshaltyperef) {
2244 if (minfo->marshaltyperef) {
2245 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246 if (!is_ok (error)) {
2247 sigbuffer_free (&buf);
2250 str = type_get_fully_qualified_name (marshaltype);
2252 str = mono_string_to_utf8 (minfo->marshaltype);
2254 sigbuffer_add_value (&buf, len);
2255 sigbuffer_add_mem (&buf, str, len);
2258 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2259 sigbuffer_add_value (&buf, 0);
2261 if (minfo->mcookie) {
2262 str = mono_string_to_utf8 (minfo->mcookie);
2264 sigbuffer_add_value (&buf, len);
2265 sigbuffer_add_mem (&buf, str, len);
2268 sigbuffer_add_value (&buf, 0);
2274 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275 sigbuffer_free (&buf);
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2282 MONO_REQ_GC_UNSAFE_MODE;
2284 mono_error_init (error);
2286 MonoDynamicTable *table;
2289 /* maybe this fixup should be done in the C# code */
2290 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292 table = &assembly->tables [MONO_TABLE_FIELD];
2293 fb->table_idx = table->next_idx ++;
2294 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297 values [MONO_FIELD_FLAGS] = fb->attrs;
2298 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299 return_if_nok (error);
2302 if (fb->offset != -1) {
2303 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2305 alloc_table (table, table->rows);
2306 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2310 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312 table = &assembly->tables [MONO_TABLE_CONSTANT];
2314 alloc_table (table, table->rows);
2315 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318 values [MONO_CONSTANT_TYPE] = field_type;
2319 values [MONO_CONSTANT_PADDING] = 0;
2321 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2323 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2325 alloc_table (table, table->rows);
2326 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2329 * We store it in the code section because it's simpler for now.
2332 if (mono_array_length (fb->rva_data) >= 10)
2333 stream_data_align (&assembly->code);
2334 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2336 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2339 if (fb->marshal_info) {
2340 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2342 alloc_table (table, table->rows);
2343 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346 return_if_nok (error);
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2353 MONO_REQ_GC_UNSAFE_MODE;
2355 mono_error_init (error);
2358 guint32 nparams = 0;
2359 MonoReflectionMethodBuilder *mb = fb->get_method;
2360 MonoReflectionMethodBuilder *smb = fb->set_method;
2363 if (mb && mb->parameters)
2364 nparams = mono_array_length (mb->parameters);
2365 if (!mb && smb && smb->parameters)
2366 nparams = mono_array_length (smb->parameters) - 1;
2367 sigbuffer_init (&buf, 32);
2368 if (fb->call_conv & 0x20)
2369 sigbuffer_add_byte (&buf, 0x28);
2371 sigbuffer_add_byte (&buf, 0x08);
2372 sigbuffer_add_value (&buf, nparams);
2374 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2377 for (i = 0; i < nparams; ++i) {
2378 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379 encode_reflection_type (assembly, pt, &buf, error);
2383 } else if (smb && smb->parameters) {
2384 /* the property type is the last param */
2385 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2389 for (i = 0; i < nparams; ++i) {
2390 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391 encode_reflection_type (assembly, pt, &buf, error);
2396 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2401 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402 sigbuffer_free (&buf);
2405 sigbuffer_free (&buf);
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2412 MONO_REQ_GC_UNSAFE_MODE;
2414 mono_error_init (error);
2416 MonoDynamicTable *table;
2418 guint num_methods = 0;
2422 * we need to set things in the following tables:
2423 * PROPERTYMAP (info already filled in _get_type_info ())
2424 * PROPERTY (rows already preallocated in _get_type_info ())
2425 * METHOD (method info already done with the generic method code)
2429 table = &assembly->tables [MONO_TABLE_PROPERTY];
2430 pb->table_idx = table->next_idx ++;
2431 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435 return_if_nok (error);
2438 /* FIXME: we still don't handle 'other' methods */
2439 if (pb->get_method) num_methods ++;
2440 if (pb->set_method) num_methods ++;
2442 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443 table->rows += num_methods;
2444 alloc_table (table, table->rows);
2446 if (pb->get_method) {
2447 semaidx = table->next_idx ++;
2448 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2453 if (pb->set_method) {
2454 semaidx = table->next_idx ++;
2455 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2460 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462 table = &assembly->tables [MONO_TABLE_CONSTANT];
2464 alloc_table (table, table->rows);
2465 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468 values [MONO_CONSTANT_TYPE] = field_type;
2469 values [MONO_CONSTANT_PADDING] = 0;
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2476 MONO_REQ_GC_UNSAFE_MODE;
2479 MonoDynamicTable *table;
2481 guint num_methods = 0;
2485 * we need to set things in the following tables:
2486 * EVENTMAP (info already filled in _get_type_info ())
2487 * EVENT (rows already preallocated in _get_type_info ())
2488 * METHOD (method info already done with the generic method code)
2491 table = &assembly->tables [MONO_TABLE_EVENT];
2492 eb->table_idx = table->next_idx ++;
2493 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2494 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2495 values [MONO_EVENT_FLAGS] = eb->attrs;
2496 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, &error);
2497 mono_error_raise_exception (&error); /* FIXME don't raise here */
2498 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2501 * FIXME: we still don't handle 'other' methods
2503 if (eb->add_method) num_methods ++;
2504 if (eb->remove_method) num_methods ++;
2505 if (eb->raise_method) num_methods ++;
2507 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2508 table->rows += num_methods;
2509 alloc_table (table, table->rows);
2511 if (eb->add_method) {
2512 semaidx = table->next_idx ++;
2513 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2514 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2515 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2516 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2518 if (eb->remove_method) {
2519 semaidx = table->next_idx ++;
2520 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2521 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2522 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2523 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2525 if (eb->raise_method) {
2526 semaidx = table->next_idx ++;
2527 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2528 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2529 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2530 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2535 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2537 MONO_REQ_GC_UNSAFE_MODE;
2540 MonoDynamicTable *table;
2541 guint32 num_constraints, i;
2545 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2546 num_constraints = gparam->iface_constraints ?
2547 mono_array_length (gparam->iface_constraints) : 0;
2548 table->rows += num_constraints;
2549 if (gparam->base_type)
2551 alloc_table (table, table->rows);
2553 if (gparam->base_type) {
2554 table_idx = table->next_idx ++;
2555 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2557 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, &error);
2558 mono_error_raise_exception (&error); /* FIXME don't raise here */
2559 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2560 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2563 for (i = 0; i < num_constraints; i++) {
2564 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2565 gparam->iface_constraints, gpointer, i);
2567 table_idx = table->next_idx ++;
2568 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2570 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, &error);
2571 mono_error_raise_exception (&error); /* FIXME don't raise here */
2573 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2574 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2579 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2581 MONO_REQ_GC_UNSAFE_MODE;
2583 GenericParamTableEntry *entry;
2586 * The GenericParam table must be sorted according to the `owner' field.
2587 * We need to do this sorting prior to writing the GenericParamConstraint
2588 * table, since we have to use the final GenericParam table indices there
2589 * and they must also be sorted.
2592 entry = g_new0 (GenericParamTableEntry, 1);
2593 entry->owner = owner;
2594 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2595 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2596 entry->gparam = gparam;
2598 g_ptr_array_add (assembly->gen_params, entry);
2602 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2604 MONO_REQ_GC_UNSAFE_MODE;
2606 MonoDynamicTable *table;
2607 MonoGenericParam *param;
2611 mono_error_init (error);
2613 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2614 table_idx = table->next_idx ++;
2615 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2617 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2618 return_val_if_nok (error, FALSE);
2620 param = gparam_type->data.generic_param;
2622 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2623 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2624 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2625 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2627 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2630 encode_constraints (entry->gparam, table_idx, assembly);
2636 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2638 MONO_REQ_GC_UNSAFE_MODE;
2640 MonoDynamicTable *table;
2643 guint32 cols [MONO_ASSEMBLY_SIZE];
2647 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2650 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2651 table = &assembly->tables [MONO_TABLE_MODULEREF];
2652 token = table->next_idx ++;
2654 alloc_table (table, table->rows);
2655 values = table->values + token * MONO_MODULEREF_SIZE;
2656 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2658 token <<= MONO_RESOLUTION_SCOPE_BITS;
2659 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2660 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2665 if (assembly_is_dynamic (image->assembly))
2667 memset (cols, 0, sizeof (cols));
2669 /* image->assembly->image is the manifest module */
2670 image = image->assembly->image;
2671 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2674 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2675 token = table->next_idx ++;
2677 alloc_table (table, table->rows);
2678 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2679 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2680 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2681 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2682 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2683 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2684 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2685 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2686 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2688 if (strcmp ("", image->assembly->aname.culture)) {
2689 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2690 image->assembly->aname.culture);
2693 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2694 guchar pubtoken [9];
2696 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2697 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2699 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2701 token <<= MONO_RESOLUTION_SCOPE_BITS;
2702 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2703 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2708 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2710 MONO_REQ_GC_NEUTRAL_MODE;
2712 MonoDynamicTable *table;
2717 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2720 sigbuffer_init (&buf, 32);
2721 switch (type->type) {
2722 case MONO_TYPE_FNPTR:
2724 case MONO_TYPE_SZARRAY:
2725 case MONO_TYPE_ARRAY:
2727 case MONO_TYPE_MVAR:
2728 case MONO_TYPE_GENERICINST:
2729 encode_type (assembly, type, &buf);
2731 case MONO_TYPE_CLASS:
2732 case MONO_TYPE_VALUETYPE: {
2733 MonoClass *k = mono_class_from_mono_type (type);
2734 if (!k || !k->generic_container) {
2735 sigbuffer_free (&buf);
2738 encode_type (assembly, type, &buf);
2742 sigbuffer_free (&buf);
2746 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2747 if (assembly->save) {
2748 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2749 alloc_table (table, table->rows + 1);
2750 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2751 values [MONO_TYPESPEC_SIGNATURE] = token;
2753 sigbuffer_free (&buf);
2755 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2756 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2762 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2764 MONO_REQ_GC_UNSAFE_MODE;
2766 MonoDynamicTable *table;
2768 guint32 token, scope, enclosing;
2771 /* if the type requires a typespec, we must try that first*/
2772 if (try_typespec && (token = create_typespec (assembly, type)))
2774 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2777 klass = mono_class_from_mono_type (type);
2779 klass = mono_class_from_mono_type (type);
2782 * If it's in the same module and not a generic type parameter:
2784 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2785 (type->type != MONO_TYPE_MVAR)) {
2786 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2787 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2788 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2792 if (klass->nested_in) {
2793 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2794 /* get the typeref idx of the enclosing type */
2795 enclosing >>= MONO_TYPEDEFORREF_BITS;
2796 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2798 scope = resolution_scope_from_image (assembly, klass->image);
2800 table = &assembly->tables [MONO_TABLE_TYPEREF];
2801 if (assembly->save) {
2802 alloc_table (table, table->rows + 1);
2803 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2804 values [MONO_TYPEREF_SCOPE] = scope;
2805 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2806 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2808 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2809 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2811 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2816 * Despite the name, we handle also TypeSpec (with the above helper).
2819 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2821 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2824 #ifndef DISABLE_REFLECTION_EMIT
2826 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2828 MONO_REQ_GC_NEUTRAL_MODE;
2830 MonoDynamicTable *table;
2832 guint32 token, pclass;
2834 switch (parent & MONO_TYPEDEFORREF_MASK) {
2835 case MONO_TYPEDEFORREF_TYPEREF:
2836 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2838 case MONO_TYPEDEFORREF_TYPESPEC:
2839 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2841 case MONO_TYPEDEFORREF_TYPEDEF:
2842 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2845 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2848 /* extract the index */
2849 parent >>= MONO_TYPEDEFORREF_BITS;
2851 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2853 if (assembly->save) {
2854 alloc_table (table, table->rows + 1);
2855 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2856 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2857 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2858 values [MONO_MEMBERREF_SIGNATURE] = sig;
2861 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2868 * Insert a memberef row into the metadata: the token that point to the memberref
2869 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2870 * mono_image_get_fieldref_token()).
2871 * The sig param is an index to an already built signature.
2874 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2876 MONO_REQ_GC_NEUTRAL_MODE;
2878 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2879 return mono_image_add_memberef_row (assembly, parent, name, sig);
2884 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2886 MONO_REQ_GC_NEUTRAL_MODE;
2889 MonoMethodSignature *sig;
2891 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2893 if (create_typespec) {
2894 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2899 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2900 if (token && !create_typespec)
2903 g_assert (!method->is_inflated);
2906 * A methodref signature can't contain an unmanaged calling convention.
2908 sig = mono_metadata_signature_dup (mono_method_signature (method));
2909 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2910 sig->call_convention = MONO_CALL_DEFAULT;
2911 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2912 method->name, method_encode_signature (assembly, sig));
2914 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2917 if (create_typespec) {
2918 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2919 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2920 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2922 if (assembly->save) {
2925 alloc_table (table, table->rows + 1);
2926 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2927 values [MONO_METHODSPEC_METHOD] = token;
2928 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2931 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2933 /*methodspec and memberef tokens are diferent, */
2934 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2941 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2943 guint32 token, parent, sig;
2944 ReflectionMethodBuilder rmb;
2945 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2947 mono_error_init (error);
2948 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2952 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2956 * A methodref signature can't contain an unmanaged calling convention.
2957 * Since some flags are encoded as part of call_conv, we need to check against it.
2959 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2960 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2962 sig = method_builder_encode_signature (assembly, &rmb, error);
2963 return_val_if_nok (error, 0);
2965 if (tb->generic_params)
2966 parent = create_generic_typespec (assembly, tb);
2968 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2969 return_val_if_nok (error, 0);
2971 parent = mono_image_typedef_or_ref (assembly, t);
2974 char *name = mono_string_to_utf8 (method->name);
2976 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2979 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2985 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2986 const gchar *name, guint32 sig)
2988 MonoDynamicTable *table;
2992 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2994 if (assembly->save) {
2995 alloc_table (table, table->rows + 1);
2996 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2997 values [MONO_MEMBERREF_CLASS] = original;
2998 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2999 values [MONO_MEMBERREF_SIGNATURE] = sig;
3002 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3009 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3013 guint32 nparams = mono_array_length (mb->generic_params);
3016 if (!assembly->save)
3019 sigbuffer_init (&buf, 32);
3021 sigbuffer_add_value (&buf, 0xa);
3022 sigbuffer_add_value (&buf, nparams);
3024 for (i = 0; i < nparams; i++) {
3025 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3026 sigbuffer_add_value (&buf, i);
3029 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3030 sigbuffer_free (&buf);
3035 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3037 MonoDynamicTable *table;
3039 guint32 token, mtoken = 0;
3041 mono_error_init (error);
3042 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3046 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3048 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3049 if (!mono_error_ok (error))
3052 switch (mono_metadata_token_table (mtoken)) {
3053 case MONO_TABLE_MEMBERREF:
3054 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3056 case MONO_TABLE_METHOD:
3057 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3060 g_assert_not_reached ();
3063 if (assembly->save) {
3064 alloc_table (table, table->rows + 1);
3065 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3066 values [MONO_METHODSPEC_METHOD] = mtoken;
3067 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3070 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3073 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3078 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3082 mono_error_init (error);
3084 if (mb->generic_params && create_methodspec)
3085 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3087 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3091 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3092 if (!mono_error_ok (error))
3094 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3099 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3101 guint32 token, parent, sig;
3102 ReflectionMethodBuilder rmb;
3104 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3106 mono_error_init (error);
3108 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3112 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3115 if (tb->generic_params)
3116 parent = create_generic_typespec (assembly, tb);
3118 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3119 return_val_if_nok (error, 0);
3120 parent = mono_image_typedef_or_ref (assembly, type);
3123 name = mono_string_to_utf8 (rmb.name);
3124 sig = method_builder_encode_signature (assembly, &rmb, error);
3125 return_val_if_nok (error, 0);
3127 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3130 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3136 is_field_on_inst (MonoClassField *field)
3138 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3142 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3145 get_field_on_inst_generic_type (MonoClassField *field)
3147 MonoClass *klass, *gtd;
3148 MonoDynamicGenericClass *dgclass;
3151 g_assert (is_field_on_inst (field));
3153 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3155 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3156 field_index = field - dgclass->fields;
3157 return dgclass->field_generic_types [field_index];
3160 klass = field->parent;
3161 gtd = klass->generic_class->container_class;
3163 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3164 field_index = field - klass->fields;
3165 return gtd->fields [field_index].type;
3168 g_assert_not_reached ();
3172 #ifndef DISABLE_REFLECTION_EMIT
3174 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3180 g_assert (field->parent);
3182 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3186 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3187 int index = field - field->parent->fields;
3188 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3190 if (is_field_on_inst (field))
3191 type = get_field_on_inst_generic_type (field);
3193 type = mono_field_get_type (field);
3195 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3196 mono_field_get_name (field),
3197 fieldref_encode_signature (assembly, field->parent->image, type));
3198 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3203 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3208 MonoGenericClass *gclass;
3212 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215 if (is_sre_field_builder (mono_object_class (f->fb))) {
3216 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3217 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3218 mono_error_raise_exception (&error); /* FIXME don't raise here */
3219 klass = mono_class_from_mono_type (type);
3220 gclass = type->data.generic_class;
3221 g_assert (gclass->is_dynamic);
3223 name = mono_string_to_utf8 (fb->name);
3224 guint32 sig_token = field_encode_signature (assembly, fb, &error);
3225 mono_error_raise_exception (&error); /* FIXME don't raise here */
3226 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3228 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3230 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3232 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3233 mono_error_raise_exception (&error); /* FIXME don't raise here */
3234 klass = mono_class_from_mono_type (type);
3236 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3237 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3239 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3240 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3243 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3248 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3252 MonoGenericClass *gclass;
3255 mono_error_init (error);
3257 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3259 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3263 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3264 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3265 ReflectionMethodBuilder rmb;
3268 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3269 return_val_if_nok (error, 0);
3270 klass = mono_class_from_mono_type (type);
3272 gclass = type->data.generic_class;
3273 g_assert (gclass->is_dynamic);
3275 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278 sig = method_builder_encode_signature (assembly, &rmb, error);
3279 return_val_if_nok (error, 0);
3281 name = mono_string_to_utf8 (rmb.name);
3283 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3285 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3286 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3288 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3289 return_val_if_nok (error, 0);
3290 klass = mono_class_from_mono_type (type);
3292 sig = method_encode_signature (assembly, mono_method_signature (mm));
3293 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3295 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3296 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3300 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3305 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3308 MonoGenericContext tmp_context;
3309 MonoType **type_argv;
3310 MonoGenericInst *ginst;
3311 MonoMethod *method, *inflated;
3314 mono_error_init (error);
3316 init_type_builder_generics ((MonoObject*)m->inst);
3318 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3319 return_val_if_nok (error, NULL);
3321 klass = method->klass;
3323 if (m->method_args == NULL)
3326 if (method->is_inflated)
3327 method = ((MonoMethodInflated *) method)->declaring;
3329 count = mono_array_length (m->method_args);
3331 type_argv = g_new0 (MonoType *, count);
3332 for (i = 0; i < count; i++) {
3333 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3334 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3335 return_val_if_nok (error, NULL);
3337 ginst = mono_metadata_get_generic_inst (count, type_argv);
3340 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3341 tmp_context.method_inst = ginst;
3343 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3344 mono_error_assert_ok (error);
3349 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3351 guint32 sig, token = 0;
3355 mono_error_init (error);
3357 if (m->method_args) {
3358 MonoMethod *inflated;
3360 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3361 return_val_if_nok (error, 0);
3363 if (create_methodspec)
3364 token = mono_image_get_methodspec_token (assembly, inflated);
3366 token = mono_image_get_inflated_method_token (assembly, inflated);
3370 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3374 if (is_sre_method_builder (mono_object_class (m->mb))) {
3375 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3376 MonoGenericClass *gclass;
3377 ReflectionMethodBuilder rmb;
3380 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3381 return_val_if_nok (error, 0);
3382 klass = mono_class_from_mono_type (type);
3383 gclass = type->data.generic_class;
3384 g_assert (gclass->is_dynamic);
3386 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389 sig = method_builder_encode_signature (assembly, &rmb, error);
3390 return_val_if_nok (error, 0);
3392 name = mono_string_to_utf8 (rmb.name);
3394 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3396 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3397 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3399 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3400 return_val_if_nok (error, 0);
3401 klass = mono_class_from_mono_type (type);
3403 sig = method_encode_signature (assembly, mono_method_signature (mm));
3404 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3406 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3407 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3410 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3419 guint32 nparams = context->method_inst->type_argc;
3422 if (!assembly->save)
3425 sigbuffer_init (&buf, 32);
3427 * FIXME: vararg, explicit_this, differenc call_conv values...
3429 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3430 sigbuffer_add_value (&buf, nparams);
3432 for (i = 0; i < nparams; i++)
3433 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3435 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3436 sigbuffer_free (&buf);
3441 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3443 MonoDynamicTable *table;
3445 guint32 token, mtoken = 0, sig;
3446 MonoMethodInflated *imethod;
3447 MonoMethod *declaring;
3449 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3451 g_assert (method->is_inflated);
3452 imethod = (MonoMethodInflated *) method;
3453 declaring = imethod->declaring;
3455 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3456 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3458 if (!mono_method_signature (declaring)->generic_param_count)
3461 switch (mono_metadata_token_table (mtoken)) {
3462 case MONO_TABLE_MEMBERREF:
3463 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3465 case MONO_TABLE_METHOD:
3466 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469 g_assert_not_reached ();
3472 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3474 if (assembly->save) {
3475 alloc_table (table, table->rows + 1);
3476 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3477 values [MONO_METHODSPEC_METHOD] = mtoken;
3478 values [MONO_METHODSPEC_SIGNATURE] = sig;
3481 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3488 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3490 MonoMethodInflated *imethod;
3493 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3497 g_assert (method->is_inflated);
3498 imethod = (MonoMethodInflated *) method;
3500 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3501 token = method_encode_methodspec (assembly, method);
3503 guint32 sig = method_encode_signature (
3504 assembly, mono_method_signature (imethod->declaring));
3505 token = mono_image_get_memberref_token (
3506 assembly, &method->klass->byval_arg, method->name, sig);
3509 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3514 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3516 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3520 token = mono_image_get_memberref_token (
3521 assembly, &m->klass->byval_arg, m->name, sig);
3527 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3530 MonoDynamicTable *table;
3539 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3540 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3541 * Because of this, we must not insert it into the `typeref' hash table.
3543 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3544 mono_error_raise_exception (&error); /* FIXME don't raise here */
3545 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3549 sigbuffer_init (&buf, 32);
3551 g_assert (tb->generic_params);
3552 klass = mono_class_from_mono_type (type);
3554 if (tb->generic_container)
3555 mono_reflection_create_generic_class (tb);
3557 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3558 g_assert (klass->generic_container);
3559 sigbuffer_add_value (&buf, klass->byval_arg.type);
3560 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3562 count = mono_array_length (tb->generic_params);
3563 sigbuffer_add_value (&buf, count);
3564 for (i = 0; i < count; i++) {
3565 MonoReflectionGenericParam *gparam;
3567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3568 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3569 mono_error_raise_exception (&error); /* FIXME don't raise here */
3571 encode_type (assembly, gparam_type, &buf);
3574 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3576 if (assembly->save) {
3577 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3578 alloc_table (table, table->rows + 1);
3579 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3580 values [MONO_TYPESPEC_SIGNATURE] = token;
3582 sigbuffer_free (&buf);
3584 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3585 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3591 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3594 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3597 int i, count, len, pos;
3602 count += mono_array_length (modreq);
3604 count += mono_array_length (modopt);
3607 return mono_metadata_type_dup (NULL, type);
3609 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3610 t = (MonoType *)g_malloc (len);
3611 memcpy (t, type, MONO_SIZEOF_TYPE);
3613 t->num_mods = count;
3616 for (i = 0; i < mono_array_length (modreq); ++i) {
3617 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3618 mono_error_raise_exception (&error); /* FIXME don't raise here */
3619 t->modifiers [pos].required = 1;
3620 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3625 for (i = 0; i < mono_array_length (modopt); ++i) {
3626 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3627 mono_error_raise_exception (&error); /* FIXME don't raise here */
3628 t->modifiers [pos].required = 0;
3629 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3638 init_type_builder_generics (MonoObject *type)
3640 MonoReflectionTypeBuilder *tb;
3642 if (!is_sre_type_builder(mono_object_class (type)))
3644 tb = (MonoReflectionTypeBuilder *)type;
3646 if (tb && tb->generic_container)
3647 mono_reflection_create_generic_class (tb);
3651 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3654 MonoDynamicTable *table;
3655 MonoType *custom = NULL, *type;
3657 guint32 token, pclass, parent, sig;
3660 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3664 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3665 mono_error_raise_exception (&error); /* FIXME don't raise here */
3666 /* FIXME: is this call necessary? */
3667 mono_class_from_mono_type (typeb);
3668 name = mono_string_to_utf8 (fb->name);
3670 /*FIXME this is one more layer of ugliness due how types are created.*/
3671 init_type_builder_generics (fb->type);
3673 /* fb->type does not include the custom modifiers */
3674 /* FIXME: We should do this in one place when a fieldbuilder is created */
3675 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3676 mono_error_raise_exception (&error); /* FIXME don't raise here */
3678 if (fb->modreq || fb->modopt)
3679 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3681 sig = fieldref_encode_signature (assembly, NULL, type);
3684 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3685 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3687 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3688 parent >>= MONO_TYPEDEFORREF_BITS;
3690 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3692 if (assembly->save) {
3693 alloc_table (table, table->rows + 1);
3694 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3695 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3696 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3697 values [MONO_MEMBERREF_SIGNATURE] = sig;
3700 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3702 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3708 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3715 if (!assembly->save)
3718 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3719 g_assert (helper->type == 2);
3721 if (helper->arguments)
3722 nargs = mono_array_length (helper->arguments);
3726 sigbuffer_init (&buf, 32);
3728 /* Encode calling convention */
3729 /* Change Any to Standard */
3730 if ((helper->call_conv & 0x03) == 0x03)
3731 helper->call_conv = 0x01;
3732 /* explicit_this implies has_this */
3733 if (helper->call_conv & 0x40)
3734 helper->call_conv &= 0x20;
3736 if (helper->call_conv == 0) { /* Unmanaged */
3737 idx = helper->unmanaged_call_conv - 1;
3740 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3741 if (helper->call_conv & 0x02) /* varargs */
3745 sigbuffer_add_byte (&buf, idx);
3746 sigbuffer_add_value (&buf, nargs);
3747 encode_reflection_type (assembly, helper->return_type, &buf, &error);
3748 if (!is_ok (&error))
3750 for (i = 0; i < nargs; ++i) {
3751 MonoArray *modreqs = NULL;
3752 MonoArray *modopts = NULL;
3753 MonoReflectionType *pt;
3755 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3756 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3757 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3758 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3760 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3761 if (!is_ok (&error))
3763 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3764 encode_reflection_type (assembly, pt, &buf, &error);
3765 if (!is_ok (&error))
3768 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3769 sigbuffer_free (&buf);
3773 sigbuffer_free (&buf);
3774 mono_error_raise_exception (&error); /* FIXME don't raise here */
3775 g_assert_not_reached ();
3779 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3782 MonoDynamicTable *table;
3785 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3786 idx = table->next_idx ++;
3788 alloc_table (table, table->rows);
3789 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3791 values [MONO_STAND_ALONE_SIGNATURE] =
3792 mono_reflection_encode_sighelper (assembly, helper);
3798 reflection_cc_to_file (int call_conv) {
3799 switch (call_conv & 0x3) {
3801 case 1: return MONO_CALL_DEFAULT;
3802 case 2: return MONO_CALL_VARARG;
3804 g_assert_not_reached ();
3808 #endif /* !DISABLE_REFLECTION_EMIT */
3812 MonoMethodSignature *sig;
3817 #ifndef DISABLE_REFLECTION_EMIT
3819 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3825 MonoMethodSignature *sig;
3829 name = mono_string_to_utf8 (m->name);
3830 nparams = mono_array_length (m->parameters);
3831 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3833 sig->sentinelpos = -1;
3834 sig->call_convention = reflection_cc_to_file (m->call_conv);
3835 sig->param_count = nparams;
3837 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3838 mono_error_raise_exception (&error); /* FIXME don't raise here */
3840 sig->ret = &mono_defaults.void_class->byval_arg;
3842 mtype = mono_reflection_type_get_handle (m->parent, &error);
3843 mono_error_raise_exception (&error); /* FIXME don't raise here */
3845 for (i = 0; i < nparams; ++i) {
3846 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3847 mono_error_raise_exception (&error); /* FIXME don't raise here */
3850 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3851 am = (ArrayMethod *)tmp->data;
3852 if (strcmp (name, am->name) == 0 &&
3853 mono_metadata_type_equal (am->parent, mtype) &&
3854 mono_metadata_signature_equal (am->sig, sig)) {
3857 m->table_idx = am->token & 0xffffff;
3861 am = g_new0 (ArrayMethod, 1);
3865 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3866 method_encode_signature (assembly, sig));
3867 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3868 m->table_idx = am->token & 0xffffff;
3873 * Insert into the metadata tables all the info about the TypeBuilder tb.
3874 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3877 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3879 MonoDynamicTable *table;
3881 int i, is_object = 0, is_system = 0;
3884 mono_error_init (error);
3886 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3887 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3888 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3889 n = mono_string_to_utf8 (tb->name);
3890 if (strcmp (n, "Object") == 0)
3892 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3894 n = mono_string_to_utf8 (tb->nspace);
3895 if (strcmp (n, "System") == 0)
3897 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3899 if (tb->parent && !(is_system && is_object) &&
3900 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3901 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3902 return_val_if_nok (error, FALSE);
3903 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3905 values [MONO_TYPEDEF_EXTENDS] = 0;
3907 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3908 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3911 * if we have explicitlayout or sequentiallayouts, output data in the
3912 * ClassLayout table.
3914 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3915 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3916 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3918 alloc_table (table, table->rows);
3919 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3920 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3921 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3922 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3925 /* handle interfaces */
3926 if (tb->interfaces) {
3927 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3929 table->rows += mono_array_length (tb->interfaces);
3930 alloc_table (table, table->rows);
3931 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3932 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3933 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3934 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3935 return_val_if_nok (error, FALSE);
3936 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3937 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3938 values += MONO_INTERFACEIMPL_SIZE;
3944 table = &assembly->tables [MONO_TABLE_FIELD];
3945 table->rows += tb->num_fields;
3946 alloc_table (table, table->rows);
3947 for (i = 0; i < tb->num_fields; ++i) {
3948 mono_image_get_field_info (
3949 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3950 return_val_if_nok (error, FALSE);
3954 /* handle constructors */
3956 table = &assembly->tables [MONO_TABLE_METHOD];
3957 table->rows += mono_array_length (tb->ctors);
3958 alloc_table (table, table->rows);
3959 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3960 if (!mono_image_get_ctor_info (domain,
3961 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3967 /* handle methods */
3969 table = &assembly->tables [MONO_TABLE_METHOD];
3970 table->rows += tb->num_methods;
3971 alloc_table (table, table->rows);
3972 for (i = 0; i < tb->num_methods; ++i) {
3973 if (!mono_image_get_method_info (
3974 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3979 /* Do the same with properties etc.. */
3980 if (tb->events && mono_array_length (tb->events)) {
3981 table = &assembly->tables [MONO_TABLE_EVENT];
3982 table->rows += mono_array_length (tb->events);
3983 alloc_table (table, table->rows);
3984 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3986 alloc_table (table, table->rows);
3987 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3988 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3989 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3990 for (i = 0; i < mono_array_length (tb->events); ++i)
3991 mono_image_get_event_info (
3992 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3994 if (tb->properties && mono_array_length (tb->properties)) {
3995 table = &assembly->tables [MONO_TABLE_PROPERTY];
3996 table->rows += mono_array_length (tb->properties);
3997 alloc_table (table, table->rows);
3998 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4000 alloc_table (table, table->rows);
4001 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4002 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4003 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4004 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4005 mono_image_get_property_info (
4006 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4007 return_val_if_nok (error, FALSE);
4011 /* handle generic parameters */
4012 if (tb->generic_params) {
4013 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4014 table->rows += mono_array_length (tb->generic_params);
4015 alloc_table (table, table->rows);
4016 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4017 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4019 mono_image_get_generic_param_info (
4020 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4024 mono_image_add_decl_security (assembly,
4025 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4028 MonoDynamicTable *ntable;
4030 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4031 ntable->rows += mono_array_length (tb->subtypes);
4032 alloc_table (ntable, ntable->rows);
4033 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4035 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4036 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4038 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4039 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4040 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4041 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4042 mono_string_to_utf8 (tb->name), tb->table_idx,
4043 ntable->next_idx, ntable->rows);*/
4044 values += MONO_NESTED_CLASS_SIZE;
4054 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4058 mono_ptr_array_append (*types, type);
4060 if (!type->subtypes)
4063 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4064 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4065 collect_types (types, subtype);
4070 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4072 if ((*type1)->table_idx < (*type2)->table_idx)
4075 if ((*type1)->table_idx > (*type2)->table_idx)
4082 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4085 mono_error_init (error);
4088 for (i = 0; i < mono_array_length (pinfo); ++i) {
4089 MonoReflectionParamBuilder *pb;
4090 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4093 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4101 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4104 mono_error_init (error);
4106 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4109 for (i = 0; i < tb->num_fields; ++i) {
4110 MonoReflectionFieldBuilder* fb;
4111 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4112 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4117 for (i = 0; i < mono_array_length (tb->events); ++i) {
4118 MonoReflectionEventBuilder* eb;
4119 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4120 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4124 if (tb->properties) {
4125 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4126 MonoReflectionPropertyBuilder* pb;
4127 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4128 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4133 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4134 MonoReflectionCtorBuilder* cb;
4135 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4136 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4137 !params_add_cattrs (assembly, cb->pinfo, error))
4143 for (i = 0; i < tb->num_methods; ++i) {
4144 MonoReflectionMethodBuilder* mb;
4145 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4146 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4147 !params_add_cattrs (assembly, mb->pinfo, error))
4153 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4154 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4163 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4167 mono_error_init (error);
4169 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4172 if (moduleb->global_methods) {
4173 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4174 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4175 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4176 !params_add_cattrs (assembly, mb->pinfo, error))
4181 if (moduleb->global_fields) {
4182 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4183 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4184 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4189 if (moduleb->types) {
4190 for (i = 0; i < moduleb->num_types; ++i) {
4191 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4200 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4202 MonoDynamicTable *table;
4206 char *b = blob_size;
4209 table = &assembly->tables [MONO_TABLE_FILE];
4211 alloc_table (table, table->rows);
4212 values = table->values + table->next_idx * MONO_FILE_SIZE;
4213 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4214 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4215 if (image_is_dynamic (module->image)) {
4216 /* This depends on the fact that the main module is emitted last */
4217 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4218 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4221 path = g_strdup (module->image->name);
4223 mono_sha1_get_digest_from_file (path, hash);
4226 mono_metadata_encode_value (20, b, &b);
4227 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4228 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4233 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4235 MonoDynamicTable *table;
4238 table = &assembly->tables [MONO_TABLE_MODULE];
4239 mb->table_idx = table->next_idx ++;
4240 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4241 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4244 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4245 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4246 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4247 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4251 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4252 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4254 MonoDynamicTable *table;
4258 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4259 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4262 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4264 alloc_table (table, table->rows);
4265 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4267 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4268 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4269 if (klass->nested_in)
4270 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4272 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4273 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4274 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4276 res = table->next_idx;
4280 /* Emit nested types */
4281 if (klass->ext && klass->ext->nested_classes) {
4284 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4285 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4292 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4293 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4299 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4300 mono_error_raise_exception (&error); /* FIXME don't raise here */
4302 klass = mono_class_from_mono_type (t);
4304 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4306 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4307 parent_index, assembly);
4311 * We need to do this ourselves since klass->nested_classes is not set up.
4314 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4315 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4320 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4321 guint32 module_index, MonoDynamicImage *assembly)
4323 MonoImage *image = module->image;
4327 t = &image->tables [MONO_TABLE_TYPEDEF];
4329 for (i = 0; i < t->rows; ++i) {
4331 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4332 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4334 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4335 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4340 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4342 MonoDynamicTable *table;
4344 guint32 scope, scope_idx, impl, current_idx;
4345 gboolean forwarder = TRUE;
4346 gpointer iter = NULL;
4349 if (klass->nested_in) {
4350 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4353 scope = resolution_scope_from_image (assembly, klass->image);
4354 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4355 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4356 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4359 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4362 alloc_table (table, table->rows);
4363 current_idx = table->next_idx;
4364 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4366 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4367 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4368 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4369 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4370 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4374 while ((nested = mono_class_get_nested_types (klass, &iter)))
4375 add_exported_type (assemblyb, assembly, nested, current_idx);
4379 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4385 if (!assemblyb->type_forwarders)
4388 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4389 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4394 type = mono_reflection_type_get_handle (t, &error);
4395 mono_error_assert_ok (&error);
4398 klass = mono_class_from_mono_type (type);
4400 add_exported_type (assemblyb, assembly, klass, 0);
4404 #define align_pointer(base,p)\
4406 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4408 (p) += 4 - (__diff & 3);\
4412 compare_constants (const void *a, const void *b)
4414 const guint32 *a_values = (const guint32 *)a;
4415 const guint32 *b_values = (const guint32 *)b;
4416 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4420 compare_semantics (const void *a, const void *b)
4422 const guint32 *a_values = (const guint32 *)a;
4423 const guint32 *b_values = (const guint32 *)b;
4424 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4427 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4431 compare_custom_attrs (const void *a, const void *b)
4433 const guint32 *a_values = (const guint32 *)a;
4434 const guint32 *b_values = (const guint32 *)b;
4436 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4440 compare_field_marshal (const void *a, const void *b)
4442 const guint32 *a_values = (const guint32 *)a;
4443 const guint32 *b_values = (const guint32 *)b;
4445 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4449 compare_nested (const void *a, const void *b)
4451 const guint32 *a_values = (const guint32 *)a;
4452 const guint32 *b_values = (const guint32 *)b;
4454 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4458 compare_genericparam (const void *a, const void *b)
4461 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4462 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4464 if ((*b_entry)->owner == (*a_entry)->owner) {
4465 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4466 mono_error_assert_ok (&error);
4467 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4468 mono_error_assert_ok (&error);
4470 mono_type_get_generic_param_num (a_type) -
4471 mono_type_get_generic_param_num (b_type);
4473 return (*a_entry)->owner - (*b_entry)->owner;
4477 compare_declsecurity_attrs (const void *a, const void *b)
4479 const guint32 *a_values = (const guint32 *)a;
4480 const guint32 *b_values = (const guint32 *)b;
4482 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4486 compare_interface_impl (const void *a, const void *b)
4488 const guint32 *a_values = (const guint32 *)a;
4489 const guint32 *b_values = (const guint32 *)b;
4491 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4495 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4499 pad_heap (MonoDynamicStream *sh)
4501 if (sh->index & 3) {
4502 int sz = 4 - (sh->index & 3);
4503 memset (sh->data + sh->index, 0, sz);
4510 MonoDynamicStream *stream;
4514 * build_compressed_metadata() fills in the blob of data that represents the
4515 * raw metadata as it will be saved in the PE file. The five streams are output
4516 * and the metadata tables are comnpressed from the guint32 array representation,
4517 * to the compressed on-disk format.
4520 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4522 MonoDynamicTable *table;
4524 guint64 valid_mask = 0;
4525 guint64 sorted_mask;
4526 guint32 heapt_size = 0;
4527 guint32 meta_size = 256; /* allow for header and other stuff */
4528 guint32 table_offset;
4529 guint32 ntables = 0;
4535 struct StreamDesc stream_desc [5];
4537 mono_error_init (error);
4539 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4540 for (i = 0; i < assembly->gen_params->len; i++) {
4541 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4542 if (!write_generic_param_entry (assembly, entry, error))
4546 stream_desc [0].name = "#~";
4547 stream_desc [0].stream = &assembly->tstream;
4548 stream_desc [1].name = "#Strings";
4549 stream_desc [1].stream = &assembly->sheap;
4550 stream_desc [2].name = "#US";
4551 stream_desc [2].stream = &assembly->us;
4552 stream_desc [3].name = "#Blob";
4553 stream_desc [3].stream = &assembly->blob;
4554 stream_desc [4].name = "#GUID";
4555 stream_desc [4].stream = &assembly->guid;
4557 /* tables that are sorted */
4558 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4559 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4560 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4561 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4562 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4563 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4564 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4566 /* Compute table sizes */
4567 /* the MonoImage has already been created in mono_image_basic_init() */
4568 meta = &assembly->image;
4570 /* sizes should be multiple of 4 */
4571 pad_heap (&assembly->blob);
4572 pad_heap (&assembly->guid);
4573 pad_heap (&assembly->sheap);
4574 pad_heap (&assembly->us);
4576 /* Setup the info used by compute_sizes () */
4577 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4578 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4579 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4581 meta_size += assembly->blob.index;
4582 meta_size += assembly->guid.index;
4583 meta_size += assembly->sheap.index;
4584 meta_size += assembly->us.index;
4586 for (i=0; i < MONO_TABLE_NUM; ++i)
4587 meta->tables [i].rows = assembly->tables [i].rows;
4589 for (i = 0; i < MONO_TABLE_NUM; i++){
4590 if (meta->tables [i].rows == 0)
4592 valid_mask |= (guint64)1 << i;
4594 meta->tables [i].row_size = mono_metadata_compute_size (
4595 meta, i, &meta->tables [i].size_bitfield);
4596 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4598 heapt_size += 24; /* #~ header size */
4599 heapt_size += ntables * 4;
4600 /* make multiple of 4 */
4603 meta_size += heapt_size;
4604 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4605 p = (unsigned char*)meta->raw_metadata;
4606 /* the metadata signature */
4607 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4608 /* version numbers and 4 bytes reserved */
4609 int16val = (guint16*)p;
4610 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4611 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4613 /* version string */
4614 int32val = (guint32*)p;
4615 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4617 memcpy (p, meta->version, strlen (meta->version));
4618 p += GUINT32_FROM_LE (*int32val);
4619 align_pointer (meta->raw_metadata, p);
4620 int16val = (guint16*)p;
4621 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4622 *int16val = GUINT16_TO_LE (5); /* number of streams */
4626 * write the stream info.
4628 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4629 table_offset += 3; table_offset &= ~3;
4631 assembly->tstream.index = heapt_size;
4632 for (i = 0; i < 5; ++i) {
4633 int32val = (guint32*)p;
4634 stream_desc [i].stream->offset = table_offset;
4635 *int32val++ = GUINT32_TO_LE (table_offset);
4636 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4637 table_offset += GUINT32_FROM_LE (*int32val);
4638 table_offset += 3; table_offset &= ~3;
4640 strcpy ((char*)p, stream_desc [i].name);
4641 p += strlen (stream_desc [i].name) + 1;
4642 align_pointer (meta->raw_metadata, p);
4645 * now copy the data, the table stream header and contents goes first.
4647 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4648 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4649 int32val = (guint32*)p;
4650 *int32val = GUINT32_TO_LE (0); /* reserved */
4653 *p++ = 2; /* version */
4656 if (meta->idx_string_wide)
4658 if (meta->idx_guid_wide)
4660 if (meta->idx_blob_wide)
4663 *p++ = 1; /* reserved */
4664 int64val = (guint64*)p;
4665 *int64val++ = GUINT64_TO_LE (valid_mask);
4666 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4668 int32val = (guint32*)p;
4669 for (i = 0; i < MONO_TABLE_NUM; i++){
4670 if (meta->tables [i].rows == 0)
4672 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4674 p = (unsigned char*)int32val;
4676 /* sort the tables that still need sorting */
4677 table = &assembly->tables [MONO_TABLE_CONSTANT];
4679 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4680 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4682 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4683 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4685 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4686 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4688 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4689 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4691 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4692 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4693 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4695 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4696 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4698 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4700 /* compress the tables */
4701 for (i = 0; i < MONO_TABLE_NUM; i++){
4704 guint32 bitfield = meta->tables [i].size_bitfield;
4705 if (!meta->tables [i].rows)
4707 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4708 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4709 meta->tables [i].base = (char*)p;
4710 for (row = 1; row <= meta->tables [i].rows; ++row) {
4711 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4712 for (col = 0; col < assembly->tables [i].columns; ++col) {
4713 switch (mono_metadata_table_size (bitfield, col)) {
4715 *p++ = values [col];
4718 *p++ = values [col] & 0xff;
4719 *p++ = (values [col] >> 8) & 0xff;
4722 *p++ = values [col] & 0xff;
4723 *p++ = (values [col] >> 8) & 0xff;
4724 *p++ = (values [col] >> 16) & 0xff;
4725 *p++ = (values [col] >> 24) & 0xff;
4728 g_assert_not_reached ();
4732 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4735 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4736 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4737 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4738 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4739 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4741 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4747 * Some tables in metadata need to be sorted according to some criteria, but
4748 * when methods and fields are first created with reflection, they may be assigned a token
4749 * that doesn't correspond to the final token they will get assigned after the sorting.
4750 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4751 * with the reflection objects that represent them. Once all the tables are set up, the
4752 * reflection objects will contains the correct table index. fixup_method() will fixup the
4753 * tokens for the method with ILGenerator @ilgen.
4756 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4758 guint32 code_idx = GPOINTER_TO_UINT (value);
4759 MonoReflectionILTokenInfo *iltoken;
4760 MonoReflectionFieldBuilder *field;
4761 MonoReflectionCtorBuilder *ctor;
4762 MonoReflectionMethodBuilder *method;
4763 MonoReflectionTypeBuilder *tb;
4764 MonoReflectionArrayMethod *am;
4766 unsigned char *target;
4768 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4769 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4770 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4771 switch (target [3]) {
4772 case MONO_TABLE_FIELD:
4773 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4774 field = (MonoReflectionFieldBuilder *)iltoken->member;
4775 idx = field->table_idx;
4776 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4777 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4778 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4780 g_assert_not_reached ();
4783 case MONO_TABLE_METHOD:
4784 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4785 method = (MonoReflectionMethodBuilder *)iltoken->member;
4786 idx = method->table_idx;
4787 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4788 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4789 idx = ctor->table_idx;
4790 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4791 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4792 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4793 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4795 g_assert_not_reached ();
4798 case MONO_TABLE_TYPEDEF:
4799 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4800 g_assert_not_reached ();
4801 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4802 idx = tb->table_idx;
4804 case MONO_TABLE_MEMBERREF:
4805 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4806 am = (MonoReflectionArrayMethod*)iltoken->member;
4807 idx = am->table_idx;
4808 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4809 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4810 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4811 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4812 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4813 g_assert (m->klass->generic_class || m->klass->generic_container);
4815 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4817 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4818 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4819 g_assert (is_field_on_inst (f));
4821 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4822 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4824 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4826 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4828 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4831 g_assert_not_reached ();
4834 case MONO_TABLE_METHODSPEC:
4835 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4836 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4837 g_assert (mono_method_signature (m)->generic_param_count);
4839 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4841 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4844 g_assert_not_reached ();
4848 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4850 target [0] = idx & 0xff;
4851 target [1] = (idx >> 8) & 0xff;
4852 target [2] = (idx >> 16) & 0xff;
4859 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4860 * value is not known when the table is emitted.
4863 fixup_cattrs (MonoDynamicImage *assembly)
4865 MonoDynamicTable *table;
4867 guint32 type, i, idx, token;
4870 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4872 for (i = 0; i < table->rows; ++i) {
4873 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4875 type = values [MONO_CUSTOM_ATTR_TYPE];
4876 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4877 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4878 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4879 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4882 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4883 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4884 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4885 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4886 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4887 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4888 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4889 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4896 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4898 MonoDynamicTable *table;
4901 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4903 alloc_table (table, table->rows);
4904 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4905 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4906 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4907 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4908 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4913 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4915 MonoDynamicTable *table;
4919 char *b = blob_size;
4921 guint32 idx, offset;
4923 if (rsrc->filename) {
4924 name = mono_string_to_utf8 (rsrc->filename);
4925 sname = g_path_get_basename (name);
4927 table = &assembly->tables [MONO_TABLE_FILE];
4929 alloc_table (table, table->rows);
4930 values = table->values + table->next_idx * MONO_FILE_SIZE;
4931 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4932 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4935 mono_sha1_get_digest_from_file (name, hash);
4936 mono_metadata_encode_value (20, b, &b);
4937 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4938 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4940 idx = table->next_idx++;
4942 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4948 data = mono_array_addr (rsrc->data, char, 0);
4949 len = mono_array_length (rsrc->data);
4955 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4956 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4957 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4958 mono_image_add_stream_data (&assembly->resources, data, len);
4962 * The entry should be emitted into the MANIFESTRESOURCE table of
4963 * the main module, but that needs to reference the FILE table
4964 * which isn't emitted yet.
4971 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4975 set_version_from_string (MonoString *version, guint32 *values)
4977 gchar *ver, *p, *str;
4980 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4981 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4982 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4983 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4986 ver = str = mono_string_to_utf8 (version);
4987 for (i = 0; i < 4; ++i) {
4988 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4994 /* handle Revision and Build */
5004 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5008 char *b = blob_size;
5013 len = mono_array_length (pkey);
5014 mono_metadata_encode_value (len, b, &b);
5015 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5016 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5018 assembly->public_key = (guint8 *)g_malloc (len);
5019 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5020 assembly->public_key_len = len;
5022 /* Special case: check for ECMA key (16 bytes) */
5023 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5024 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5025 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5026 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5027 /* minimum key size (in 2.0) is 384 bits */
5028 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5030 /* FIXME - verifier */
5031 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5032 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5034 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5040 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5042 MonoDynamicTable *table;
5043 MonoDynamicImage *assembly;
5044 MonoReflectionAssemblyBuilder *assemblyb;
5048 guint32 module_index;
5050 assemblyb = moduleb->assemblyb;
5051 assembly = moduleb->dynamic_image;
5052 domain = mono_object_domain (assemblyb);
5054 /* Emit ASSEMBLY table */
5055 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5056 alloc_table (table, 1);
5057 values = table->values + MONO_ASSEMBLY_SIZE;
5058 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5059 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5060 if (assemblyb->culture) {
5061 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5063 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5065 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5066 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5067 set_version_from_string (assemblyb->version, values);
5069 /* Emit FILE + EXPORTED_TYPE table */
5071 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5073 MonoReflectionModuleBuilder *file_module =
5074 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5075 if (file_module != moduleb) {
5076 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5078 if (file_module->types) {
5079 for (j = 0; j < file_module->num_types; ++j) {
5080 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5081 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5086 if (assemblyb->loaded_modules) {
5087 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5088 MonoReflectionModule *file_module =
5089 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5090 mono_image_fill_file_table (domain, file_module, assembly);
5092 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5095 if (assemblyb->type_forwarders)
5096 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5098 /* Emit MANIFESTRESOURCE table */
5100 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5102 MonoReflectionModuleBuilder *file_module =
5103 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5104 /* The table for the main module is emitted later */
5105 if (file_module != moduleb) {
5107 if (file_module->resources) {
5108 int len = mono_array_length (file_module->resources);
5109 for (j = 0; j < len; ++j) {
5110 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5111 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5118 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5121 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5122 * for the modulebuilder @moduleb.
5123 * At the end of the process, method and field tokens are fixed up and the
5124 * on-disk compressed metadata representation is created.
5125 * Return TRUE on success, or FALSE on failure and sets @error
5128 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5130 MonoDynamicTable *table;
5131 MonoDynamicImage *assembly;
5132 MonoReflectionAssemblyBuilder *assemblyb;
5138 mono_error_init (error);
5140 assemblyb = moduleb->assemblyb;
5141 assembly = moduleb->dynamic_image;
5142 domain = mono_object_domain (assemblyb);
5144 if (assembly->text_rva)
5147 assembly->text_rva = START_TEXT_RVA;
5149 if (moduleb->is_main) {
5150 mono_image_emit_manifest (moduleb);
5153 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5154 table->rows = 1; /* .<Module> */
5156 alloc_table (table, table->rows);
5158 * Set the first entry.
5160 values = table->values + table->columns;
5161 values [MONO_TYPEDEF_FLAGS] = 0;
5162 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5163 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5164 values [MONO_TYPEDEF_EXTENDS] = 0;
5165 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5166 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5169 * handle global methods
5170 * FIXME: test what to do when global methods are defined in multiple modules.
5172 if (moduleb->global_methods) {
5173 table = &assembly->tables [MONO_TABLE_METHOD];
5174 table->rows += mono_array_length (moduleb->global_methods);
5175 alloc_table (table, table->rows);
5176 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5177 if (!mono_image_get_method_info (
5178 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5182 if (moduleb->global_fields) {
5183 table = &assembly->tables [MONO_TABLE_FIELD];
5184 table->rows += mono_array_length (moduleb->global_fields);
5185 alloc_table (table, table->rows);
5186 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5187 mono_image_get_field_info (
5188 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5195 table = &assembly->tables [MONO_TABLE_MODULE];
5196 alloc_table (table, 1);
5197 mono_image_fill_module_table (domain, moduleb, assembly);
5199 /* Collect all types into a list sorted by their table_idx */
5200 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5203 for (i = 0; i < moduleb->num_types; ++i) {
5204 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5205 collect_types (&types, type);
5208 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5209 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5210 table->rows += mono_ptr_array_size (types);
5211 alloc_table (table, table->rows);
5214 * Emit type names + namespaces at one place inside the string heap,
5215 * so load_class_names () needs to touch fewer pages.
5217 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5218 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5219 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5221 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5222 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5223 string_heap_insert_mstring (&assembly->sheap, tb->name);
5226 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5227 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5228 if (!mono_image_get_type_info (domain, type, assembly, error))
5233 * table->rows is already set above and in mono_image_fill_module_table.
5235 /* add all the custom attributes at the end, once all the indexes are stable */
5236 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5239 /* CAS assembly permissions */
5240 if (assemblyb->permissions_minimum)
5241 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5242 if (assemblyb->permissions_optional)
5243 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5244 if (assemblyb->permissions_refused)
5245 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5247 if (!module_add_cattrs (assembly, moduleb, error))
5251 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5253 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5254 * the final tokens and don't need another fixup pass. */
5256 if (moduleb->global_methods) {
5257 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5258 MonoReflectionMethodBuilder *mb = mono_array_get (
5259 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5260 if (!mono_image_add_methodimpl (assembly, mb, error))
5265 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5266 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5267 if (type->methods) {
5268 for (j = 0; j < type->num_methods; ++j) {
5269 MonoReflectionMethodBuilder *mb = mono_array_get (
5270 type->methods, MonoReflectionMethodBuilder*, j);
5272 if (!mono_image_add_methodimpl (assembly, mb, error))
5278 fixup_cattrs (assembly);
5281 mono_ptr_array_destroy (types);
5284 return mono_error_ok (error);
5287 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5290 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5292 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5295 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5299 guint32 import_lookup_table;
5303 guint32 import_address_table_rva;
5311 #ifndef DISABLE_REFLECTION_EMIT
5314 * mono_image_insert_string:
5315 * @module: module builder object
5318 * Insert @str into the user string stream of @module.
5321 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5323 MonoDynamicImage *assembly;
5328 if (!module->dynamic_image)
5329 mono_image_module_basic_init (module);
5331 assembly = module->dynamic_image;
5333 if (assembly->save) {
5334 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5335 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5336 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5338 char *swapped = g_malloc (2 * mono_string_length (str));
5339 const char *p = (const char*)mono_string_chars (str);
5341 swap_with_size (swapped, p, 2, mono_string_length (str));
5342 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5346 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5348 mono_image_add_stream_data (&assembly->us, "", 1);
5350 idx = assembly->us.index ++;
5353 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5355 return MONO_TOKEN_STRING | idx;
5359 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5363 MonoMethodSignature *sig;
5365 mono_error_init (error);
5367 klass = obj->vtable->klass;
5368 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5369 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5370 MonoMethodSignature *old;
5371 guint32 sig_token, parent;
5374 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5376 nargs = mono_array_length (opt_param_types);
5377 old = mono_method_signature (method);
5378 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5380 sig->hasthis = old->hasthis;
5381 sig->explicit_this = old->explicit_this;
5382 sig->call_convention = old->call_convention;
5383 sig->generic_param_count = old->generic_param_count;
5384 sig->param_count = old->param_count + nargs;
5385 sig->sentinelpos = old->param_count;
5386 sig->ret = old->ret;
5388 for (i = 0; i < old->param_count; i++)
5389 sig->params [i] = old->params [i];
5391 for (i = 0; i < nargs; i++) {
5392 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5393 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5394 if (!is_ok (error)) goto fail;
5397 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5398 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5399 parent >>= MONO_TYPEDEFORREF_BITS;
5401 parent <<= MONO_MEMBERREF_PARENT_BITS;
5402 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5404 sig_token = method_encode_signature (assembly, sig);
5405 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5406 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5407 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5408 ReflectionMethodBuilder rmb;
5409 guint32 parent, sig_token;
5410 int nopt_args, nparams, ngparams, i;
5412 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5415 rmb.opt_types = opt_param_types;
5416 nopt_args = mono_array_length (opt_param_types);
5418 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5419 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5420 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5422 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5423 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5424 sig->call_convention = rmb.call_conv;
5425 sig->generic_param_count = ngparams;
5426 sig->param_count = nparams + nopt_args;
5427 sig->sentinelpos = nparams;
5428 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5429 if (!is_ok (error)) goto fail;
5431 for (i = 0; i < nparams; i++) {
5432 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5433 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5434 if (!is_ok (error)) goto fail;
5437 for (i = 0; i < nopt_args; i++) {
5438 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5439 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5440 if (!is_ok (error)) goto fail;
5443 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5447 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5448 if (!mono_error_ok (error))
5450 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5452 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5453 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5455 char *name = mono_string_to_utf8 (rmb.name);
5456 token = mono_image_get_varargs_method_token (
5457 assembly, parent, name, sig_token);
5460 g_error ("requested method token for %s\n", klass->name);
5463 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5464 register_dyn_token (assembly, token, obj);
5467 g_assert (!mono_error_ok (error));
5472 * mono_image_create_token:
5473 * @assembly: a dynamic assembly
5475 * @register_token: Whenever to register the token in the assembly->tokens hash.
5477 * Get a token to insert in the IL code stream for the given MemberInfo.
5478 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5479 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5483 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5484 gboolean create_open_instance, gboolean register_token,
5490 mono_error_init (error);
5492 klass = obj->vtable->klass;
5494 /* Check for user defined reflection objects */
5495 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5496 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5497 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5501 if (strcmp (klass->name, "MethodBuilder") == 0) {
5502 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5505 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5506 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5508 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5509 if (!mono_error_ok (error))
5512 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5513 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5514 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5515 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5517 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5518 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5520 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5521 if (!mono_error_ok (error))
5524 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5525 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5526 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5527 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5528 if (tb->generic_params) {
5529 token = mono_image_get_generic_field_token (assembly, fb);
5531 if (tb->module->dynamic_image == assembly) {
5532 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5534 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5537 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5538 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5539 if (create_open_instance && tb->generic_params) {
5541 init_type_builder_generics (obj);
5542 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5543 return_val_if_nok (error, 0);
5544 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5545 token = mono_metadata_token_from_dor (token);
5546 } else if (tb->module->dynamic_image == assembly) {
5547 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5550 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5551 return_val_if_nok (error, 0);
5552 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5554 } else if (strcmp (klass->name, "MonoType") == 0) {
5555 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5556 return_val_if_nok (error, 0);
5557 MonoClass *mc = mono_class_from_mono_type (type);
5558 token = mono_metadata_token_from_dor (
5559 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5560 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5561 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5562 return_val_if_nok (error, 0);
5563 token = mono_metadata_token_from_dor (
5564 mono_image_typedef_or_ref (assembly, type));
5565 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5566 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5567 return_val_if_nok (error, 0);
5568 token = mono_metadata_token_from_dor (
5569 mono_image_typedef_or_ref (assembly, type));
5570 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5571 strcmp (klass->name, "MonoMethod") == 0 ||
5572 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5573 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5574 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5575 if (m->method->is_inflated) {
5576 if (create_open_instance)
5577 token = mono_image_get_methodspec_token (assembly, m->method);
5579 token = mono_image_get_inflated_method_token (assembly, m->method);
5580 } else if ((m->method->klass->image == &assembly->image) &&
5581 !m->method->klass->generic_class) {
5582 static guint32 method_table_idx = 0xffffff;
5583 if (m->method->klass->wastypebuilder) {
5584 /* we use the same token as the one that was assigned
5585 * to the Methodbuilder.
5586 * FIXME: do the equivalent for Fields.
5588 token = m->method->token;
5591 * Each token should have a unique index, but the indexes are
5592 * assigned by managed code, so we don't know about them. An
5593 * easy solution is to count backwards...
5595 method_table_idx --;
5596 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5599 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5601 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5602 } else if (strcmp (klass->name, "MonoField") == 0) {
5603 MonoReflectionField *f = (MonoReflectionField *)obj;
5604 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5605 static guint32 field_table_idx = 0xffffff;
5607 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5609 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5611 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5612 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5613 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5614 token = mono_image_get_array_token (assembly, m);
5615 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5616 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5617 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5618 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5619 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5620 return_val_if_nok (error, 0);
5621 token = mono_metadata_token_from_dor (
5622 mono_image_typedef_or_ref (assembly, type));
5623 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5624 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5625 token = mono_image_get_field_on_inst_token (assembly, f);
5626 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5627 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5628 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5629 if (!mono_error_ok (error))
5631 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5632 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5633 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5634 if (!mono_error_ok (error))
5636 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5637 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5638 return_val_if_nok (error, 0);
5639 token = mono_metadata_token_from_dor (
5640 mono_image_typedef_or_ref (assembly, type));
5642 g_error ("requested token for %s\n", klass->name);
5646 mono_image_register_token (assembly, token, obj);
5652 * mono_image_register_token:
5654 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5655 * the Module.ResolveXXXToken () methods to work.
5658 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5662 dynamic_image_lock (assembly);
5663 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5665 /* There could be multiple MethodInfo objects with the same token */
5666 //g_assert (prev == obj);
5668 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5670 dynamic_image_unlock (assembly);
5673 static MonoDynamicImage*
5674 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5676 static const guchar entrycode [16] = {0xff, 0x25, 0};
5677 MonoDynamicImage *image;
5680 const char *version;
5682 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5683 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5685 version = mono_get_runtime_info ()->runtime_version;
5688 /* The MonoGHashTable's need GC tracking */
5689 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5691 image = g_new0 (MonoDynamicImage, 1);
5694 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5696 /*g_print ("created image %p\n", image);*/
5697 /* keep in sync with image.c */
5698 image->image.name = assembly_name;
5699 image->image.assembly_name = image->image.name; /* they may be different */
5700 image->image.module_name = module_name;
5701 image->image.version = g_strdup (version);
5702 image->image.md_version_major = 1;
5703 image->image.md_version_minor = 1;
5704 image->image.dynamic = TRUE;
5706 image->image.references = g_new0 (MonoAssembly*, 1);
5707 image->image.references [0] = NULL;
5709 mono_image_init (&image->image);
5711 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");
5712 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5713 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5714 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5715 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5716 image->handleref = g_hash_table_new (NULL, NULL);
5717 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");
5718 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5719 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");
5720 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");
5721 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5722 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5723 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5724 image->gen_params = g_ptr_array_new ();
5725 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5727 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5728 string_heap_init (&image->sheap);
5729 mono_image_add_stream_data (&image->us, "", 1);
5730 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5731 /* import tables... */
5732 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5733 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5734 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5735 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5736 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5737 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5738 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5739 stream_data_align (&image->code);
5741 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5743 for (i=0; i < MONO_TABLE_NUM; ++i) {
5744 image->tables [i].next_idx = 1;
5745 image->tables [i].columns = table_sizes [i];
5748 image->image.assembly = (MonoAssembly*)assembly;
5749 image->run = assembly->run;
5750 image->save = assembly->save;
5751 image->pe_kind = 0x1; /* ILOnly */
5752 image->machine = 0x14c; /* I386 */
5754 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5756 dynamic_images_lock ();
5758 if (!dynamic_images)
5759 dynamic_images = g_ptr_array_new ();
5761 g_ptr_array_add (dynamic_images, image);
5763 dynamic_images_unlock ();
5770 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5776 release_hashtable (MonoGHashTable **hash)
5779 mono_g_hash_table_destroy (*hash);
5785 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5787 release_hashtable (&image->token_fixups);
5788 release_hashtable (&image->handleref_managed);
5789 release_hashtable (&image->tokens);
5790 release_hashtable (&image->remapped_tokens);
5791 release_hashtable (&image->generic_def_objects);
5792 release_hashtable (&image->methodspec);
5795 // Free dynamic image pass one: Free resources but not image itself
5797 mono_dynamic_image_free (MonoDynamicImage *image)
5799 MonoDynamicImage *di = image;
5804 mono_g_hash_table_destroy (di->methodspec);
5806 g_hash_table_destroy (di->typespec);
5808 g_hash_table_destroy (di->typeref);
5810 g_hash_table_destroy (di->handleref);
5811 if (di->handleref_managed)
5812 mono_g_hash_table_destroy (di->handleref_managed);
5814 mono_g_hash_table_destroy (di->tokens);
5815 if (di->remapped_tokens)
5816 mono_g_hash_table_destroy (di->remapped_tokens);
5817 if (di->generic_def_objects)
5818 mono_g_hash_table_destroy (di->generic_def_objects);
5819 if (di->blob_cache) {
5820 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5821 g_hash_table_destroy (di->blob_cache);
5823 if (di->standalonesig_cache)
5824 g_hash_table_destroy (di->standalonesig_cache);
5825 for (list = di->array_methods; list; list = list->next) {
5826 ArrayMethod *am = (ArrayMethod *)list->data;
5831 g_list_free (di->array_methods);
5832 if (di->gen_params) {
5833 for (i = 0; i < di->gen_params->len; i++) {
5834 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5835 mono_gc_deregister_root ((char*) &entry->gparam);
5838 g_ptr_array_free (di->gen_params, TRUE);
5840 if (di->token_fixups)
5841 mono_g_hash_table_destroy (di->token_fixups);
5842 if (di->method_to_table_idx)
5843 g_hash_table_destroy (di->method_to_table_idx);
5844 if (di->field_to_table_idx)
5845 g_hash_table_destroy (di->field_to_table_idx);
5846 if (di->method_aux_hash)
5847 g_hash_table_destroy (di->method_aux_hash);
5848 if (di->vararg_aux_hash)
5849 g_hash_table_destroy (di->vararg_aux_hash);
5850 g_free (di->strong_name);
5851 g_free (di->win32_res);
5853 g_free (di->public_key);
5855 /*g_print ("string heap destroy for image %p\n", di);*/
5856 mono_dynamic_stream_reset (&di->sheap);
5857 mono_dynamic_stream_reset (&di->code);
5858 mono_dynamic_stream_reset (&di->resources);
5859 mono_dynamic_stream_reset (&di->us);
5860 mono_dynamic_stream_reset (&di->blob);
5861 mono_dynamic_stream_reset (&di->tstream);
5862 mono_dynamic_stream_reset (&di->guid);
5863 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5864 g_free (di->tables [i].values);
5867 dynamic_images_lock ();
5870 g_ptr_array_remove (dynamic_images, di);
5872 dynamic_images_unlock ();
5875 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5877 mono_dynamic_image_free_image (MonoDynamicImage *image)
5879 /* See create_dynamic_mono_image () */
5881 /* Allocated using GC_MALLOC */
5887 #ifndef DISABLE_REFLECTION_EMIT
5890 * mono_image_basic_init:
5891 * @assembly: an assembly builder object
5893 * Create the MonoImage that represents the assembly builder and setup some
5894 * of the helper hash table and the basic metadata streams.
5897 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5899 MonoDynamicAssembly *assembly;
5900 MonoDynamicImage *image;
5901 MonoDomain *domain = mono_object_domain (assemblyb);
5903 if (assemblyb->dynamic_assembly)
5907 /* assembly->assembly.image might be GC allocated */
5908 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5910 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5913 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5915 assembly->assembly.ref_count = 1;
5916 assembly->assembly.dynamic = TRUE;
5917 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5918 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5919 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5920 if (assemblyb->culture)
5921 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5923 assembly->assembly.aname.culture = g_strdup ("");
5925 if (assemblyb->version) {
5926 char *vstr = mono_string_to_utf8 (assemblyb->version);
5927 char **version = g_strsplit (vstr, ".", 4);
5928 char **parts = version;
5929 assembly->assembly.aname.major = atoi (*parts++);
5930 assembly->assembly.aname.minor = atoi (*parts++);
5931 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5932 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5934 g_strfreev (version);
5937 assembly->assembly.aname.major = 0;
5938 assembly->assembly.aname.minor = 0;
5939 assembly->assembly.aname.build = 0;
5940 assembly->assembly.aname.revision = 0;
5943 assembly->run = assemblyb->access != 2;
5944 assembly->save = assemblyb->access != 1;
5945 assembly->domain = domain;
5947 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5948 image->initial_image = TRUE;
5949 assembly->assembly.aname.name = image->image.name;
5950 assembly->assembly.image = &image->image;
5951 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5952 /* -1 to correct for the trailing NULL byte */
5953 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5954 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5956 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5959 mono_domain_assemblies_lock (domain);
5960 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5961 mono_domain_assemblies_unlock (domain);
5963 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5965 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5967 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5970 #endif /* !DISABLE_REFLECTION_EMIT */
5972 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5975 calc_section_size (MonoDynamicImage *assembly)
5979 /* alignment constraints */
5980 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5981 g_assert ((assembly->code.index % 4) == 0);
5982 assembly->meta_size += 3;
5983 assembly->meta_size &= ~3;
5984 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5985 g_assert ((assembly->resources.index % 4) == 0);
5987 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5988 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5991 if (assembly->win32_res) {
5992 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5994 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5995 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5999 assembly->sections [MONO_SECTION_RELOC].size = 12;
6000 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6010 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6014 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6016 ResTreeNode *t1 = (ResTreeNode*)a;
6017 ResTreeNode *t2 = (ResTreeNode*)b;
6019 return t1->id - t2->id;
6023 * resource_tree_create:
6025 * Organize the resources into a resource tree.
6027 static ResTreeNode *
6028 resource_tree_create (MonoArray *win32_resources)
6030 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6034 tree = g_new0 (ResTreeNode, 1);
6036 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6037 MonoReflectionWin32Resource *win32_res =
6038 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6042 /* FIXME: BUG: this stores managed references in unmanaged memory */
6043 lang_node = g_new0 (ResTreeNode, 1);
6044 lang_node->id = win32_res->lang_id;
6045 lang_node->win32_res = win32_res;
6047 /* Create type node if neccesary */
6049 for (l = tree->children; l; l = l->next)
6050 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6051 type_node = (ResTreeNode*)l->data;
6056 type_node = g_new0 (ResTreeNode, 1);
6057 type_node->id = win32_res->res_type;
6060 * The resource types have to be sorted otherwise
6061 * Windows Explorer can't display the version information.
6063 tree->children = g_slist_insert_sorted (tree->children,
6064 type_node, resource_tree_compare_by_id);
6067 /* Create res node if neccesary */
6069 for (l = type_node->children; l; l = l->next)
6070 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6071 res_node = (ResTreeNode*)l->data;
6076 res_node = g_new0 (ResTreeNode, 1);
6077 res_node->id = win32_res->res_id;
6078 type_node->children = g_slist_append (type_node->children, res_node);
6081 res_node->children = g_slist_append (res_node->children, lang_node);
6088 * resource_tree_encode:
6090 * Encode the resource tree into the format used in the PE file.
6093 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6096 MonoPEResourceDir dir;
6097 MonoPEResourceDirEntry dir_entry;
6098 MonoPEResourceDataEntry data_entry;
6100 guint32 res_id_entries;
6103 * For the format of the resource directory, see the article
6104 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6108 memset (&dir, 0, sizeof (dir));
6109 memset (&dir_entry, 0, sizeof (dir_entry));
6110 memset (&data_entry, 0, sizeof (data_entry));
6112 g_assert (sizeof (dir) == 16);
6113 g_assert (sizeof (dir_entry) == 8);
6114 g_assert (sizeof (data_entry) == 16);
6116 node->offset = p - begin;
6118 /* IMAGE_RESOURCE_DIRECTORY */
6119 res_id_entries = g_slist_length (node->children);
6120 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6122 memcpy (p, &dir, sizeof (dir));
6125 /* Reserve space for entries */
6127 p += sizeof (dir_entry) * res_id_entries;
6129 /* Write children */
6130 for (l = node->children; l; l = l->next) {
6131 ResTreeNode *child = (ResTreeNode*)l->data;
6133 if (child->win32_res) {
6136 child->offset = p - begin;
6138 /* IMAGE_RESOURCE_DATA_ENTRY */
6139 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6140 size = mono_array_length (child->win32_res->res_data);
6141 data_entry.rde_size = GUINT32_TO_LE (size);
6143 memcpy (p, &data_entry, sizeof (data_entry));
6144 p += sizeof (data_entry);
6146 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6149 resource_tree_encode (child, begin, p, &p);
6153 /* IMAGE_RESOURCE_ENTRY */
6154 for (l = node->children; l; l = l->next) {
6155 ResTreeNode *child = (ResTreeNode*)l->data;
6157 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6158 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6160 memcpy (entries, &dir_entry, sizeof (dir_entry));
6161 entries += sizeof (dir_entry);
6168 resource_tree_free (ResTreeNode * node)
6171 for (list = node->children; list; list = list->next)
6172 resource_tree_free ((ResTreeNode*)list->data);
6173 g_slist_free(node->children);
6178 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6183 MonoReflectionWin32Resource *win32_res;
6186 if (!assemblyb->win32_resources)
6190 * Resources are stored in a three level tree inside the PE file.
6191 * - level one contains a node for each type of resource
6192 * - level two contains a node for each resource
6193 * - level three contains a node for each instance of a resource for a
6194 * specific language.
6197 tree = resource_tree_create (assemblyb->win32_resources);
6199 /* Estimate the size of the encoded tree */
6201 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6202 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6203 size += mono_array_length (win32_res->res_data);
6205 /* Directory structure */
6206 size += mono_array_length (assemblyb->win32_resources) * 256;
6207 p = buf = (char *)g_malloc (size);
6209 resource_tree_encode (tree, p, p, &p);
6211 g_assert (p - buf <= size);
6213 assembly->win32_res = (char *)g_malloc (p - buf);
6214 assembly->win32_res_size = p - buf;
6215 memcpy (assembly->win32_res, buf, p - buf);
6218 resource_tree_free (tree);
6222 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6224 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6227 p += sizeof (MonoPEResourceDir);
6228 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6229 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6230 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6231 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6232 fixup_resource_directory (res_section, child, rva);
6234 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6235 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6238 p += sizeof (MonoPEResourceDirEntry);
6243 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6246 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6247 g_error ("WriteFile returned %d\n", GetLastError ());
6251 * mono_image_create_pefile:
6252 * @mb: a module builder object
6254 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6255 * assembly->pefile where it can be easily retrieved later in chunks.
6258 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6260 MonoMSDOSHeader *msdos;
6261 MonoDotNetHeader *header;
6262 MonoSectionTable *section;
6263 MonoCLIHeader *cli_header;
6264 guint32 size, image_size, virtual_base, text_offset;
6265 guint32 header_start, section_start, file_offset, virtual_offset;
6266 MonoDynamicImage *assembly;
6267 MonoReflectionAssemblyBuilder *assemblyb;
6268 MonoDynamicStream pefile_stream = {0};
6269 MonoDynamicStream *pefile = &pefile_stream;
6271 guint32 *rva, value;
6273 static const unsigned char msheader[] = {
6274 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6275 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6278 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6279 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6280 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6281 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6284 mono_error_init (error);
6286 assemblyb = mb->assemblyb;
6288 mono_image_basic_init (assemblyb);
6289 assembly = mb->dynamic_image;
6291 assembly->pe_kind = assemblyb->pe_kind;
6292 assembly->machine = assemblyb->machine;
6293 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6294 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6296 if (!mono_image_build_metadata (mb, error))
6300 if (mb->is_main && assemblyb->resources) {
6301 int len = mono_array_length (assemblyb->resources);
6302 for (i = 0; i < len; ++i)
6303 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6306 if (mb->resources) {
6307 int len = mono_array_length (mb->resources);
6308 for (i = 0; i < len; ++i)
6309 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6312 if (!build_compressed_metadata (assembly, error))
6316 assembly_add_win32_resources (assembly, assemblyb);
6318 nsections = calc_section_size (assembly);
6320 /* The DOS header and stub */
6321 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6322 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6324 /* the dotnet header */
6325 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6327 /* the section tables */
6328 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6330 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6331 virtual_offset = VIRT_ALIGN;
6334 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6335 if (!assembly->sections [i].size)
6338 file_offset += FILE_ALIGN - 1;
6339 file_offset &= ~(FILE_ALIGN - 1);
6340 virtual_offset += VIRT_ALIGN - 1;
6341 virtual_offset &= ~(VIRT_ALIGN - 1);
6343 assembly->sections [i].offset = file_offset;
6344 assembly->sections [i].rva = virtual_offset;
6346 file_offset += assembly->sections [i].size;
6347 virtual_offset += assembly->sections [i].size;
6348 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6351 file_offset += FILE_ALIGN - 1;
6352 file_offset &= ~(FILE_ALIGN - 1);
6354 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6356 /* back-patch info */
6357 msdos = (MonoMSDOSHeader*)pefile->data;
6358 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6360 header = (MonoDotNetHeader*)(pefile->data + header_start);
6361 header->pesig [0] = 'P';
6362 header->pesig [1] = 'E';
6364 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6365 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6366 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6367 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6368 if (assemblyb->pekind == 1) {
6370 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6373 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6376 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6378 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6379 header->pe.pe_major = 6;
6380 header->pe.pe_minor = 0;
6381 size = assembly->sections [MONO_SECTION_TEXT].size;
6382 size += FILE_ALIGN - 1;
6383 size &= ~(FILE_ALIGN - 1);
6384 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6385 size = assembly->sections [MONO_SECTION_RSRC].size;
6386 size += FILE_ALIGN - 1;
6387 size &= ~(FILE_ALIGN - 1);
6388 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6389 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6390 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6391 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6392 /* pe_rva_entry_point always at the beginning of the text section */
6393 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6395 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6396 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6397 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6398 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6399 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6400 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6401 size = section_start;
6402 size += FILE_ALIGN - 1;
6403 size &= ~(FILE_ALIGN - 1);
6404 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6406 size += VIRT_ALIGN - 1;
6407 size &= ~(VIRT_ALIGN - 1);
6408 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6411 // Translate the PEFileKind value to the value expected by the Windows loader
6417 // PEFileKinds.Dll == 1
6418 // PEFileKinds.ConsoleApplication == 2
6419 // PEFileKinds.WindowApplication == 3
6422 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6423 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6425 if (assemblyb->pekind == 3)
6430 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6432 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6433 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6434 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6435 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6436 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6437 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6439 /* fill data directory entries */
6441 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6442 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6444 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6445 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6447 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6448 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6449 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6450 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6451 /* patch entrypoint name */
6452 if (assemblyb->pekind == 1)
6453 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6455 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6456 /* patch imported function RVA name */
6457 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6458 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6460 /* the import table */
6461 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6462 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6463 /* patch imported dll RVA name and other entries in the dir */
6464 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6465 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6466 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6467 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6468 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6469 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6471 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6472 value = (assembly->text_rva + assembly->imp_names_offset);
6473 *p++ = (value) & 0xff;
6474 *p++ = (value >> 8) & (0xff);
6475 *p++ = (value >> 16) & (0xff);
6476 *p++ = (value >> 24) & (0xff);
6478 /* the CLI header info */
6479 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6480 cli_header->ch_size = GUINT32_FROM_LE (72);
6481 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6482 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6483 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6484 if (assemblyb->entry_point) {
6485 guint32 table_idx = 0;
6486 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6487 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6488 table_idx = methodb->table_idx;
6490 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6492 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6494 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6496 /* The embedded managed resources */
6497 text_offset = assembly->text_rva + assembly->code.index;
6498 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6499 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6500 text_offset += assembly->resources.index;
6501 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6502 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6503 text_offset += assembly->meta_size;
6504 if (assembly->strong_name_size) {
6505 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6506 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6507 text_offset += assembly->strong_name_size;
6510 /* write the section tables and section content */
6511 section = (MonoSectionTable*)(pefile->data + section_start);
6512 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6513 static const char section_names [][7] = {
6514 ".text", ".rsrc", ".reloc"
6516 if (!assembly->sections [i].size)
6518 strcpy (section->st_name, section_names [i]);
6519 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6520 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6521 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6522 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6523 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6524 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6525 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6529 checked_write_file (file, pefile->data, pefile->index);
6531 mono_dynamic_stream_reset (pefile);
6533 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6534 if (!assembly->sections [i].size)
6537 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6538 g_error ("SetFilePointer returned %d\n", GetLastError ());
6541 case MONO_SECTION_TEXT:
6542 /* patch entry point */
6543 p = (guchar*)(assembly->code.data + 2);
6544 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6545 *p++ = (value) & 0xff;
6546 *p++ = (value >> 8) & 0xff;
6547 *p++ = (value >> 16) & 0xff;
6548 *p++ = (value >> 24) & 0xff;
6550 checked_write_file (file, assembly->code.data, assembly->code.index);
6551 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6552 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6553 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6556 g_free (assembly->image.raw_metadata);
6558 case MONO_SECTION_RELOC: {
6562 guint16 type_and_offset;
6566 g_assert (sizeof (reloc) == 12);
6568 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6569 reloc.block_size = GUINT32_FROM_LE (12);
6572 * the entrypoint is always at the start of the text section
6573 * 3 is IMAGE_REL_BASED_HIGHLOW
6574 * 2 is patch_size_rva - text_rva
6576 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6579 checked_write_file (file, &reloc, sizeof (reloc));
6583 case MONO_SECTION_RSRC:
6584 if (assembly->win32_res) {
6586 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6587 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6588 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6592 g_assert_not_reached ();
6596 /* check that the file is properly padded */
6597 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6598 g_error ("SetFilePointer returned %d\n", GetLastError ());
6599 if (! SetEndOfFile (file))
6600 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6602 mono_dynamic_stream_reset (&assembly->code);
6603 mono_dynamic_stream_reset (&assembly->us);
6604 mono_dynamic_stream_reset (&assembly->blob);
6605 mono_dynamic_stream_reset (&assembly->guid);
6606 mono_dynamic_stream_reset (&assembly->sheap);
6608 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6609 g_hash_table_destroy (assembly->blob_cache);
6610 assembly->blob_cache = NULL;
6615 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6618 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6620 g_assert_not_reached ();
6623 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6625 #ifndef DISABLE_REFLECTION_EMIT
6627 MonoReflectionModule *
6628 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6631 MonoReflectionModule *result = NULL;
6634 MonoImageOpenStatus status;
6635 MonoDynamicAssembly *assembly;
6636 guint32 module_count;
6637 MonoImage **new_modules;
6638 gboolean *new_modules_loaded;
6640 name = mono_string_to_utf8 (fileName);
6642 image = mono_image_open (name, &status);
6645 if (status == MONO_IMAGE_ERROR_ERRNO)
6646 exc = mono_get_exception_file_not_found (fileName);
6648 exc = mono_get_exception_bad_image_format (name);
6650 mono_raise_exception (exc);
6655 assembly = ab->dynamic_assembly;
6656 image->assembly = (MonoAssembly*)assembly;
6658 module_count = image->assembly->image->module_count;
6659 new_modules = g_new0 (MonoImage *, module_count + 1);
6660 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6662 if (image->assembly->image->modules)
6663 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6664 if (image->assembly->image->modules_loaded)
6665 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6666 new_modules [module_count] = image;
6667 new_modules_loaded [module_count] = TRUE;
6668 mono_image_addref (image);
6670 g_free (image->assembly->image->modules);
6671 image->assembly->image->modules = new_modules;
6672 image->assembly->image->modules_loaded = new_modules_loaded;
6673 image->assembly->image->module_count ++;
6675 mono_assembly_load_references (image, &status);
6677 mono_image_close (image);
6678 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6681 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6682 mono_error_raise_exception (&error); /* FIXME don't raise here */
6686 #endif /* DISABLE_REFLECTION_EMIT */
6689 * We need to return always the same object for MethodInfo, FieldInfo etc..
6690 * but we need to consider the reflected type.
6691 * type uses a different hash, since it uses custom hash/equal functions.
6696 MonoClass *refclass;
6700 reflected_equal (gconstpointer a, gconstpointer b) {
6701 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6702 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6704 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6708 reflected_hash (gconstpointer a) {
6709 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6710 return mono_aligned_addr_hash (ea->item);
6713 #define CHECK_OBJECT(t,p,k) \
6719 mono_domain_lock (domain); \
6720 if (!domain->refobject_hash) \
6721 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"); \
6722 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6723 mono_domain_unlock (domain); \
6726 mono_domain_unlock (domain); \
6729 #ifdef HAVE_BOEHM_GC
6730 /* ReflectedEntry doesn't need to be GC tracked */
6731 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6732 #define FREE_REFENTRY(entry) g_free ((entry))
6733 #define REFENTRY_REQUIRES_CLEANUP
6735 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6737 #define FREE_REFENTRY(entry)
6740 #define CACHE_OBJECT(t,p,o,k) \
6743 ReflectedEntry pe; \
6745 pe.refclass = (k); \
6746 mono_domain_lock (domain); \
6747 if (!domain->refobject_hash) \
6748 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"); \
6749 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6751 ReflectedEntry *e = ALLOC_REFENTRY; \
6753 e->refclass = (k); \
6754 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6757 mono_domain_unlock (domain); \
6762 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6764 mono_domain_lock (domain);
6765 if (domain->refobject_hash) {
6767 gpointer orig_pe, orig_value;
6770 pe.refclass = klass;
6771 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6772 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6773 FREE_REFENTRY (orig_pe);
6776 mono_domain_unlock (domain);
6779 #ifdef REFENTRY_REQUIRES_CLEANUP
6781 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6783 FREE_REFENTRY (key);
6788 mono_reflection_cleanup_domain (MonoDomain *domain)
6790 if (domain->refobject_hash) {
6791 /*let's avoid scanning the whole hashtable if not needed*/
6792 #ifdef REFENTRY_REQUIRES_CLEANUP
6793 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6795 mono_g_hash_table_destroy (domain->refobject_hash);
6796 domain->refobject_hash = NULL;
6800 #ifndef DISABLE_REFLECTION_EMIT
6802 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6804 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6808 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6810 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6814 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6816 MonoDynamicImage *image = moduleb->dynamic_image;
6817 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6821 MonoImage **new_modules;
6823 char *name, *fqname;
6825 * FIXME: we already created an image in mono_image_basic_init (), but
6826 * we don't know which module it belongs to, since that is only
6827 * determined at assembly save time.
6829 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6830 name = mono_string_to_utf8 (ab->name);
6831 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6832 if (!mono_error_ok (&error)) {
6834 mono_error_raise_exception (&error);
6836 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6838 moduleb->module.image = &image->image;
6839 moduleb->dynamic_image = image;
6840 register_module (mono_object_domain (moduleb), moduleb, image);
6842 /* register the module with the assembly */
6843 ass = ab->dynamic_assembly->assembly.image;
6844 module_count = ass->module_count;
6845 new_modules = g_new0 (MonoImage *, module_count + 1);
6848 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6849 new_modules [module_count] = &image->image;
6850 mono_image_addref (&image->image);
6852 g_free (ass->modules);
6853 ass->modules = new_modules;
6854 ass->module_count ++;
6859 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6861 MonoDynamicImage *image = moduleb->dynamic_image;
6863 g_assert (type->type);
6864 image->wrappers_type = mono_class_from_mono_type (type->type);
6870 * mono_assembly_get_object:
6871 * @domain: an app domain
6872 * @assembly: an assembly
6874 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6876 MonoReflectionAssembly*
6877 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6880 MonoReflectionAssembly *result;
6881 result = mono_assembly_get_object_checked (domain, assembly, &error);
6882 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6886 * mono_assembly_get_object_checked:
6887 * @domain: an app domain
6888 * @assembly: an assembly
6890 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6892 MonoReflectionAssembly*
6893 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6895 MonoReflectionAssembly *res;
6897 mono_error_init (error);
6899 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6900 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6903 res->assembly = assembly;
6905 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6910 MonoReflectionModule*
6911 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6914 MonoReflectionModule *result;
6915 result = mono_module_get_object_checked (domain, image, &error);
6916 mono_error_raise_exception (&error);
6920 MonoReflectionModule*
6921 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6923 MonoReflectionModule *res;
6926 mono_error_init (error);
6927 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6928 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6933 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6936 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6938 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6939 basename = g_path_get_basename (image->name);
6940 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6941 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6945 if (image->assembly->image == image) {
6946 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6950 if (image->assembly->image->modules) {
6951 for (i = 0; i < image->assembly->image->module_count; i++) {
6952 if (image->assembly->image->modules [i] == image)
6953 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6955 g_assert (res->token);
6959 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6962 MonoReflectionModule*
6963 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6966 MonoReflectionModule *result;
6967 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6968 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6972 MonoReflectionModule*
6973 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6975 MonoReflectionModule *res;
6976 MonoTableInfo *table;
6977 guint32 cols [MONO_FILE_SIZE];
6979 guint32 i, name_idx;
6982 mono_error_init (error);
6984 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6988 table = &image->tables [MONO_TABLE_FILE];
6989 g_assert (table_index < table->rows);
6990 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6993 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6996 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6997 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6999 /* Check whenever the row has a corresponding row in the moduleref table */
7000 table = &image->tables [MONO_TABLE_MODULEREF];
7001 for (i = 0; i < table->rows; ++i) {
7002 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7003 val = mono_metadata_string_heap (image, name_idx);
7004 if (strcmp (val, name) == 0)
7005 res->image = image->modules [i];
7008 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7009 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7010 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7011 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7012 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7018 verify_safe_for_managed_space (MonoType *type)
7020 switch (type->type) {
7022 case MONO_TYPE_ARRAY:
7023 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7025 return verify_safe_for_managed_space (type->data.type);
7026 case MONO_TYPE_SZARRAY:
7027 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7028 case MONO_TYPE_GENERICINST: {
7029 MonoGenericInst *inst = type->data.generic_class->inst;
7033 for (i = 0; i < inst->type_argc; ++i)
7034 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7040 case MONO_TYPE_MVAR:
7048 mono_type_normalize (MonoType *type)
7051 MonoGenericClass *gclass;
7052 MonoGenericInst *ginst;
7054 MonoGenericContainer *gcontainer;
7055 MonoType **argv = NULL;
7056 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7058 if (type->type != MONO_TYPE_GENERICINST)
7061 gclass = type->data.generic_class;
7062 ginst = gclass->context.class_inst;
7063 if (!ginst->is_open)
7066 gtd = gclass->container_class;
7067 gcontainer = gtd->generic_container;
7068 argv = g_newa (MonoType*, ginst->type_argc);
7070 for (i = 0; i < ginst->type_argc; ++i) {
7071 MonoType *t = ginst->type_argv [i], *norm;
7072 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7073 is_denorm_gtd = FALSE;
7074 norm = mono_type_normalize (t);
7077 requires_rebind = TRUE;
7081 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7083 if (requires_rebind) {
7084 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7085 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7091 * mono_type_get_object:
7092 * @domain: an app domain
7095 * Return an System.MonoType object representing the type @type.
7098 mono_type_get_object (MonoDomain *domain, MonoType *type)
7101 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7102 mono_error_raise_exception (&error);
7108 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7110 MonoType *norm_type;
7111 MonoReflectionType *res;
7114 mono_error_init (error);
7116 klass = mono_class_from_mono_type (type);
7118 /*we must avoid using @type as it might have come
7119 * from a mono_metadata_type_dup and the caller
7120 * expects that is can be freed.
7121 * Using the right type from
7123 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7125 /* void is very common */
7126 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7127 return (MonoReflectionType*)domain->typeof_void;
7130 * If the vtable of the given class was already created, we can use
7131 * the MonoType from there and avoid all locking and hash table lookups.
7133 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7134 * that the resulting object is different.
7136 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7137 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7138 if (vtable && vtable->type)
7139 return (MonoReflectionType *)vtable->type;
7142 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7143 mono_domain_lock (domain);
7144 if (!domain->type_hash)
7145 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7146 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7147 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7148 mono_domain_unlock (domain);
7149 mono_loader_unlock ();
7153 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7154 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7155 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7156 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7157 * artifact of how generics are encoded and should be transparent to managed code so we
7158 * need to weed out this diference when retrieving managed System.Type objects.
7160 norm_type = mono_type_normalize (type);
7161 if (norm_type != type) {
7162 res = mono_type_get_object_checked (domain, norm_type, error);
7163 if (!mono_error_ok (error))
7165 mono_g_hash_table_insert (domain->type_hash, type, res);
7166 mono_domain_unlock (domain);
7167 mono_loader_unlock ();
7171 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7172 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7175 if (!verify_safe_for_managed_space (type)) {
7176 mono_domain_unlock (domain);
7177 mono_loader_unlock ();
7178 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7182 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7183 gboolean is_type_done = TRUE;
7184 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7185 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7186 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7188 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7189 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7191 if (gparam->owner && gparam->owner->is_method) {
7192 MonoMethod *method = gparam->owner->owner.method;
7193 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7194 is_type_done = FALSE;
7195 } else if (gparam->owner && !gparam->owner->is_method) {
7196 MonoClass *klass = gparam->owner->owner.klass;
7197 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7198 is_type_done = FALSE;
7202 /* g_assert_not_reached (); */
7203 /* should this be considered an error condition? */
7204 if (is_type_done && !type->byref) {
7205 mono_domain_unlock (domain);
7206 mono_loader_unlock ();
7207 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7210 /* This is stored in vtables/JITted code so it has to be pinned */
7211 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7212 if (!mono_error_ok (error))
7216 mono_g_hash_table_insert (domain->type_hash, type, res);
7218 if (type->type == MONO_TYPE_VOID)
7219 domain->typeof_void = (MonoObject*)res;
7221 mono_domain_unlock (domain);
7222 mono_loader_unlock ();
7227 * mono_method_get_object:
7228 * @domain: an app domain
7230 * @refclass: the reflected type (can be NULL)
7232 * Return an System.Reflection.MonoMethod object representing the method @method.
7234 MonoReflectionMethod*
7235 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7238 MonoReflectionMethod *ret = NULL;
7239 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7240 mono_error_raise_exception (&error);
7245 * mono_method_get_object_checked:
7246 * @domain: an app domain
7248 * @refclass: the reflected type (can be NULL)
7249 * @error: set on error.
7251 * Return an System.Reflection.MonoMethod object representing the method @method.
7252 * Returns NULL and sets @error on error.
7254 MonoReflectionMethod*
7255 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7258 * We use the same C representation for methods and constructors, but the type
7259 * name in C# is different.
7261 MonoReflectionType *rt;
7263 MonoReflectionMethod *ret;
7265 mono_error_init (error);
7267 if (method->is_inflated) {
7268 MonoReflectionGenericMethod *gret;
7271 refclass = method->klass;
7272 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7273 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7274 klass = mono_class_get_mono_generic_cmethod_class ();
7276 klass = mono_class_get_mono_generic_method_class ();
7278 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7279 if (!mono_error_ok (error))
7281 gret->method.method = method;
7283 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7285 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7286 if (!mono_error_ok (error))
7289 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7291 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7295 refclass = method->klass;
7297 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7298 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7299 klass = mono_class_get_mono_cmethod_class ();
7302 klass = mono_class_get_mono_method_class ();
7304 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7305 if (!mono_error_ok (error))
7307 ret->method = method;
7309 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7310 if (!mono_error_ok (error))
7313 MONO_OBJECT_SETREF (ret, reftype, rt);
7315 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7318 g_assert (!mono_error_ok (error));
7323 * mono_method_clear_object:
7325 * Clear the cached reflection objects for the dynamic method METHOD.
7328 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7331 g_assert (method_is_dynamic (method));
7333 klass = method->klass;
7335 clear_cached_object (domain, method, klass);
7336 klass = klass->parent;
7338 /* Added by mono_param_get_objects () */
7339 clear_cached_object (domain, &(method->signature), NULL);
7340 klass = method->klass;
7342 clear_cached_object (domain, &(method->signature), klass);
7343 klass = klass->parent;
7348 * mono_field_get_object:
7349 * @domain: an app domain
7353 * Return an System.Reflection.MonoField object representing the field @field
7356 MonoReflectionField*
7357 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7360 MonoReflectionField *result;
7361 result = mono_field_get_object_checked (domain, klass, field, &error);
7362 mono_error_raise_exception (&error);
7367 * mono_field_get_object_checked:
7368 * @domain: an app domain
7371 * @error: set on error
7373 * Return an System.Reflection.MonoField object representing the field @field
7374 * in class @klass. On error, returns NULL and sets @error.
7376 MonoReflectionField*
7377 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7379 MonoReflectionType *rt;
7380 MonoReflectionField *res;
7382 mono_error_init (error);
7384 CHECK_OBJECT (MonoReflectionField *, field, klass);
7385 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7390 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7392 if (is_field_on_inst (field)) {
7393 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7395 rt = mono_type_get_object_checked (domain, field->type, error);
7396 if (!mono_error_ok (error))
7399 MONO_OBJECT_SETREF (res, type, rt);
7402 rt = mono_type_get_object_checked (domain, field->type, error);
7403 if (!mono_error_ok (error))
7406 MONO_OBJECT_SETREF (res, type, rt);
7408 res->attrs = mono_field_get_flags (field);
7410 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7414 * mono_property_get_object:
7415 * @domain: an app domain
7417 * @property: a property
7419 * Return an System.Reflection.MonoProperty object representing the property @property
7422 MonoReflectionProperty*
7423 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7426 MonoReflectionProperty *result;
7427 result = mono_property_get_object_checked (domain, klass, property, &error);
7428 mono_error_raise_exception (&error);
7433 * mono_property_get_object:
7434 * @domain: an app domain
7436 * @property: a property
7437 * @error: set on error
7439 * Return an System.Reflection.MonoProperty object representing the property @property
7440 * in class @klass. On error returns NULL and sets @error.
7442 MonoReflectionProperty*
7443 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7445 MonoReflectionProperty *res;
7447 mono_error_init (error);
7449 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7450 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7454 res->property = property;
7455 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7459 * mono_event_get_object:
7460 * @domain: an app domain
7464 * Return an System.Reflection.MonoEvent object representing the event @event
7467 MonoReflectionEvent*
7468 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7471 MonoReflectionEvent *result;
7472 result = mono_event_get_object_checked (domain, klass, event, &error);
7473 mono_error_raise_exception (&error);
7478 * mono_event_get_object_checked:
7479 * @domain: an app domain
7482 * @error: set on error
7484 * Return an System.Reflection.MonoEvent object representing the event @event
7485 * in class @klass. On failure sets @error and returns NULL
7487 MonoReflectionEvent*
7488 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7490 MonoReflectionEvent *res;
7491 MonoReflectionMonoEvent *mono_event;
7493 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7494 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7497 mono_event->klass = klass;
7498 mono_event->event = event;
7499 res = (MonoReflectionEvent*)mono_event;
7500 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7504 * mono_get_reflection_missing_object:
7505 * @domain: Domain where the object lives
7507 * Returns the System.Reflection.Missing.Value singleton object
7508 * (of type System.Reflection.Missing).
7510 * Used as the value for ParameterInfo.DefaultValue when Optional
7514 mono_get_reflection_missing_object (MonoDomain *domain)
7517 static MonoClassField *missing_value_field = NULL;
7519 if (!missing_value_field) {
7520 MonoClass *missing_klass;
7521 missing_klass = mono_class_get_missing_class ();
7522 mono_class_init (missing_klass);
7523 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7524 g_assert (missing_value_field);
7526 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7532 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7535 *dbnull = mono_get_dbnull_object (domain);
7540 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7542 if (!*reflection_missing)
7543 *reflection_missing = mono_get_reflection_missing_object (domain);
7544 return *reflection_missing;
7548 * mono_param_get_objects:
7549 * @domain: an app domain
7552 * Return an System.Reflection.ParameterInfo array object representing the parameters
7553 * in the method @method.
7556 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7558 static MonoClass *System_Reflection_ParameterInfo;
7559 static MonoClass *System_Reflection_ParameterInfo_array;
7561 MonoArray *res = NULL;
7562 MonoReflectionMethod *member = NULL;
7563 MonoReflectionParameter *param = NULL;
7564 char **names = NULL, **blobs = NULL;
7565 guint32 *types = NULL;
7566 MonoType *type = NULL;
7567 MonoObject *dbnull = NULL;
7568 MonoObject *missing = NULL;
7569 MonoMarshalSpec **mspecs = NULL;
7570 MonoMethodSignature *sig = NULL;
7571 MonoVTable *pinfo_vtable;
7572 MonoReflectionType *rt;
7575 mono_error_init (&error);
7577 if (!System_Reflection_ParameterInfo_array) {
7580 klass = mono_class_get_mono_parameter_info_class ();
7582 mono_memory_barrier ();
7583 System_Reflection_ParameterInfo = klass;
7586 klass = mono_array_class_get (klass, 1);
7587 mono_memory_barrier ();
7588 System_Reflection_ParameterInfo_array = klass;
7591 sig = mono_method_signature_checked (method, &error);
7592 if (!mono_error_ok (&error))
7595 if (!sig->param_count) {
7596 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7603 /* Note: the cache is based on the address of the signature into the method
7604 * since we already cache MethodInfos with the method as keys.
7606 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7608 member = mono_method_get_object_checked (domain, method, refclass, &error);
7611 names = g_new (char *, sig->param_count);
7612 mono_method_get_param_names (method, (const char **) names);
7614 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7615 mono_method_get_marshal_info (method, mspecs);
7617 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7621 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7622 for (i = 0; i < sig->param_count; ++i) {
7623 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7627 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7631 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7633 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7635 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7637 param->PositionImpl = i;
7638 param->AttrsImpl = sig->params [i]->attrs;
7640 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7641 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7642 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7644 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7648 blobs = g_new0 (char *, sig->param_count);
7649 types = g_new0 (guint32, sig->param_count);
7650 get_default_param_value_blobs (method, blobs, types);
7653 /* Build MonoType for the type from the Constant Table */
7655 type = g_new0 (MonoType, 1);
7656 type->type = (MonoTypeEnum)types [i];
7657 type->data.klass = NULL;
7658 if (types [i] == MONO_TYPE_CLASS)
7659 type->data.klass = mono_defaults.object_class;
7660 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7661 /* For enums, types [i] contains the base type */
7663 type->type = MONO_TYPE_VALUETYPE;
7664 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7666 type->data.klass = mono_class_from_mono_type (type);
7668 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7670 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7671 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7672 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7673 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7675 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7680 if (mspecs [i + 1]) {
7681 MonoReflectionMarshalAsAttribute* mobj;
7682 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7685 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7688 mono_array_setref (res, i, param);
7698 for (i = sig->param_count; i >= 0; i--) {
7700 mono_metadata_free_marshal_spec (mspecs [i]);
7705 mono_error_raise_exception (&error); /* FIXME don't raise here */
7707 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7711 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7713 return mono_param_get_objects_internal (domain, method, NULL);
7717 * mono_method_body_get_object:
7718 * @domain: an app domain
7721 * Return an System.Reflection.MethodBody object representing the method @method.
7723 MonoReflectionMethodBody*
7724 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7727 MonoReflectionMethodBody *ret;
7728 MonoMethodHeader *header;
7730 MonoReflectionType *rt;
7731 guint32 method_rva, local_var_sig_token;
7733 unsigned char format, flags;
7736 /* for compatibility with .net */
7737 if (method_is_dynamic (method))
7738 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7740 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7742 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7743 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7744 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7745 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7746 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7749 image = method->klass->image;
7750 header = mono_method_get_header_checked (method, &error);
7751 mono_error_raise_exception (&error); /* FIXME don't raise here */
7753 if (!image_is_dynamic (image)) {
7754 /* Obtain local vars signature token */
7755 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7756 ptr = mono_image_rva_map (image, method_rva);
7757 flags = *(const unsigned char *) ptr;
7758 format = flags & METHOD_HEADER_FORMAT_MASK;
7760 case METHOD_HEADER_TINY_FORMAT:
7761 local_var_sig_token = 0;
7763 case METHOD_HEADER_FAT_FORMAT:
7767 local_var_sig_token = read32 (ptr);
7770 g_assert_not_reached ();
7773 local_var_sig_token = 0; //FIXME
7775 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7776 mono_error_raise_exception (&error); /* FIXME don't raise here */
7778 ret->init_locals = header->init_locals;
7779 ret->max_stack = header->max_stack;
7780 ret->local_var_sig_token = local_var_sig_token;
7781 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7782 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7785 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7786 for (i = 0; i < header->num_locals; ++i) {
7787 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7788 mono_error_raise_exception (&error); /* FIXME don't raise here */
7790 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7791 mono_error_raise_exception (&error); /* FIXME don't raise here */
7793 MONO_OBJECT_SETREF (info, local_type, rt);
7795 info->is_pinned = header->locals [i]->pinned;
7796 info->local_index = i;
7797 mono_array_setref (ret->locals, i, info);
7801 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7802 for (i = 0; i < header->num_clauses; ++i) {
7803 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7804 mono_error_raise_exception (&error); /* FIXME don't raise here */
7805 MonoExceptionClause *clause = &header->clauses [i];
7807 info->flags = clause->flags;
7808 info->try_offset = clause->try_offset;
7809 info->try_length = clause->try_len;
7810 info->handler_offset = clause->handler_offset;
7811 info->handler_length = clause->handler_len;
7812 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7813 info->filter_offset = clause->data.filter_offset;
7814 else if (clause->data.catch_class) {
7815 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7816 mono_error_raise_exception (&error); /* FIXME don't raise here */
7818 MONO_OBJECT_SETREF (info, catch_type, rt);
7821 mono_array_setref (ret->clauses, i, info);
7824 mono_metadata_free_mh (header);
7825 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7830 * mono_get_dbnull_object:
7831 * @domain: Domain where the object lives
7833 * Returns the System.DBNull.Value singleton object
7835 * Used as the value for ParameterInfo.DefaultValue
7838 mono_get_dbnull_object (MonoDomain *domain)
7841 static MonoClassField *dbnull_value_field = NULL;
7843 if (!dbnull_value_field) {
7844 MonoClass *dbnull_klass;
7845 dbnull_klass = mono_class_get_dbnull_class ();
7846 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7847 g_assert (dbnull_value_field);
7849 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7855 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7857 guint32 param_index, i, lastp, crow = 0;
7858 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7861 MonoClass *klass = method->klass;
7862 MonoImage *image = klass->image;
7863 MonoMethodSignature *methodsig = mono_method_signature (method);
7865 MonoTableInfo *constt;
7866 MonoTableInfo *methodt;
7867 MonoTableInfo *paramt;
7869 if (!methodsig->param_count)
7872 mono_class_init (klass);
7874 if (image_is_dynamic (klass->image)) {
7875 MonoReflectionMethodAux *aux;
7876 if (method->is_inflated)
7877 method = ((MonoMethodInflated*)method)->declaring;
7878 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7879 if (aux && aux->param_defaults) {
7880 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7881 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7886 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7887 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7888 constt = &image->tables [MONO_TABLE_CONSTANT];
7890 idx = mono_method_get_index (method) - 1;
7891 g_assert (idx != -1);
7893 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7894 if (idx + 1 < methodt->rows)
7895 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7897 lastp = paramt->rows + 1;
7899 for (i = param_index; i < lastp; ++i) {
7902 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7903 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7905 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7908 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7913 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7914 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7915 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7922 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7928 MonoType *basetype = type;
7933 klass = mono_class_from_mono_type (type);
7934 if (klass->valuetype) {
7935 object = mono_object_new_checked (domain, klass, &error);
7936 mono_error_raise_exception (&error); /* FIXME don't raise here */
7937 retval = ((gchar *) object + sizeof (MonoObject));
7938 if (klass->enumtype)
7939 basetype = mono_class_enum_basetype (klass);
7944 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7951 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7954 gboolean quoted = FALSE;
7956 memset (assembly, 0, sizeof (MonoAssemblyName));
7957 assembly->culture = "";
7958 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7965 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7976 /* Remove trailing whitespace */
7978 while (*s && g_ascii_isspace (*s))
7981 while (g_ascii_isspace (*p))
7984 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7986 assembly->major = strtoul (p, &s, 10);
7987 if (s == p || *s != '.')
7990 assembly->minor = strtoul (p, &s, 10);
7991 if (s == p || *s != '.')
7994 assembly->build = strtoul (p, &s, 10);
7995 if (s == p || *s != '.')
7998 assembly->revision = strtoul (p, &s, 10);
8002 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8004 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8005 assembly->culture = "";
8008 assembly->culture = p;
8009 while (*p && *p != ',') {
8013 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8015 if (strncmp (p, "null", 4) == 0) {
8020 while (*p && *p != ',') {
8023 len = (p - start + 1);
8024 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8025 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8026 g_strlcpy ((char*)assembly->public_key_token, start, len);
8029 while (*p && *p != ',')
8033 while (g_ascii_isspace (*p) || *p == ',') {
8047 * mono_reflection_parse_type:
8050 * Parse a type name as accepted by the GetType () method and output the info
8051 * extracted in the info structure.
8052 * the name param will be mangled, so, make a copy before passing it to this function.
8053 * The fields in info will be valid until the memory pointed to by name is valid.
8055 * See also mono_type_get_name () below.
8057 * Returns: 0 on parse error.
8060 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8061 MonoTypeNameParse *info)
8063 char *start, *p, *w, *last_point, *startn;
8064 int in_modifiers = 0;
8065 int isbyref = 0, rank = 0, isptr = 0;
8067 start = p = w = name;
8069 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8070 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8071 info->name = info->name_space = NULL;
8072 info->nested = NULL;
8073 info->modifiers = NULL;
8074 info->type_arguments = NULL;
8076 /* last_point separates the namespace from the name */
8079 while (*p == ' ') p++, start++, w++, name++;
8084 *p = 0; /* NULL terminate the name */
8086 info->nested = g_list_append (info->nested, startn);
8087 /* we have parsed the nesting namespace + name */
8091 info->name_space = start;
8093 info->name = last_point + 1;
8095 info->name_space = (char *)"";
8123 info->name_space = start;
8125 info->name = last_point + 1;
8127 info->name_space = (char *)"";
8134 if (isbyref) /* only one level allowed by the spec */
8138 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8142 if (isbyref) /* pointer to ref not okay */
8144 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8149 if (isbyref) /* array of ref and generic ref are not okay */
8151 //Decide if it's an array of a generic argument list
8156 if (*p == ',' || *p == '*' || *p == ']') { //array
8164 else if (*p == '*') /* '*' means unknown lower bound */
8165 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8172 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8174 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8177 info->type_arguments = g_ptr_array_new ();
8179 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8180 gboolean fqname = FALSE;
8182 g_ptr_array_add (info->type_arguments, subinfo);
8184 while (*p == ' ') p++;
8190 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8193 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8194 if (fqname && (*p != ']')) {
8202 while (*p && (*p != ']'))
8210 if (g_ascii_isspace (*aname)) {
8217 !assembly_name_to_aname (&subinfo->assembly, aname))
8219 } else if (fqname && (*p == ']')) {
8241 if (g_ascii_isspace (*p)) {
8248 return 0; /* missing assembly name */
8249 if (!assembly_name_to_aname (&info->assembly, p))
8255 if (info->assembly.name)
8258 // *w = 0; /* terminate class name */
8260 if (!info->name || !*info->name)
8264 /* add other consistency checks */
8270 * mono_identifier_unescape_type_name_chars:
8271 * @identifier: the display name of a mono type
8274 * The name in internal form, that is without escaping backslashes.
8276 * The string is modified in place!
8279 mono_identifier_unescape_type_name_chars(char* identifier)
8284 for (w = r = identifier; *r != 0; r++)
8302 mono_identifier_unescape_info (MonoTypeNameParse* info);
8305 unescape_each_type_argument(void* data, void* user_data)
8307 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8308 mono_identifier_unescape_info (info);
8312 unescape_each_nested_name (void* data, void* user_data)
8314 char* nested_name = (char*) data;
8315 mono_identifier_unescape_type_name_chars(nested_name);
8319 * mono_identifier_unescape_info:
8321 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8325 * Destructively updates the info by unescaping the identifiers that
8326 * comprise the type namespace, name, nested types (if any) and
8327 * generic type arguments (if any).
8329 * The resulting info has the names in internal form.
8333 mono_identifier_unescape_info (MonoTypeNameParse *info)
8337 mono_identifier_unescape_type_name_chars(info->name_space);
8338 mono_identifier_unescape_type_name_chars(info->name);
8339 // but don't escape info->assembly
8340 if (info->type_arguments)
8341 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8343 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8347 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8349 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8351 mono_identifier_unescape_info (info);
8357 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8359 gboolean type_resolve = FALSE;
8361 MonoImage *rootimage = image;
8363 if (info->assembly.name) {
8364 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8365 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8367 * This could happen in the AOT compiler case when the search hook is not
8370 assembly = image->assembly;
8372 /* then we must load the assembly ourselve - see #60439 */
8373 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8377 image = assembly->image;
8378 } else if (!image) {
8379 image = mono_defaults.corlib;
8382 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8383 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8384 image = mono_defaults.corlib;
8385 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8392 * mono_reflection_get_type_internal:
8394 * Returns: may return NULL on success, sets error on failure.
8397 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8402 gboolean bounded = FALSE;
8404 mono_error_init (error);
8406 image = mono_defaults.corlib;
8409 rootimage = mono_defaults.corlib;
8412 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8414 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8419 for (mod = info->nested; mod; mod = mod->next) {
8420 gpointer iter = NULL;
8424 mono_class_init (parent);
8426 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8428 char *nested_name, *nested_nspace;
8429 gboolean match = TRUE;
8431 lastp = strrchr ((const char *)mod->data, '.');
8433 /* Nested classes can have namespaces */
8436 nested_name = g_strdup (lastp + 1);
8437 nspace_len = lastp - (char*)mod->data;
8438 nested_nspace = (char *)g_malloc (nspace_len + 1);
8439 memcpy (nested_nspace, mod->data, nspace_len);
8440 nested_nspace [nspace_len] = '\0';
8443 nested_name = (char *)mod->data;
8444 nested_nspace = NULL;
8447 if (nested_nspace) {
8449 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8452 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8458 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8461 if (strcmp (klass->name, nested_name) != 0)
8466 g_free (nested_name);
8467 g_free (nested_nspace);
8479 if (info->type_arguments) {
8480 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8481 MonoReflectionType *the_type;
8485 for (i = 0; i < info->type_arguments->len; i++) {
8486 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8488 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8489 if (!type_args [i]) {
8495 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8499 instance = mono_reflection_bind_generic_parameters (
8500 the_type, info->type_arguments->len, type_args);
8506 klass = mono_class_from_mono_type (instance);
8509 for (mod = info->modifiers; mod; mod = mod->next) {
8510 modval = GPOINTER_TO_UINT (mod->data);
8511 if (!modval) { /* byref: must be last modifier */
8512 return &klass->this_arg;
8513 } else if (modval == -1) {
8514 klass = mono_ptr_class_get (&klass->byval_arg);
8515 } else if (modval == -2) {
8517 } else { /* array rank */
8518 klass = mono_bounded_array_class_get (klass, modval, bounded);
8522 return &klass->byval_arg;
8526 * mono_reflection_get_type:
8527 * @image: a metadata context
8528 * @info: type description structure
8529 * @ignorecase: flag for case-insensitive string compares
8530 * @type_resolve: whenever type resolve was already tried
8532 * Build a MonoType from the type description in @info.
8537 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8538 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8542 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8544 MonoReflectionAssemblyBuilder *abuilder;
8548 mono_error_init (error);
8549 g_assert (assembly_is_dynamic (assembly));
8550 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8554 /* Enumerate all modules */
8557 if (abuilder->modules) {
8558 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8559 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8560 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8563 if (!mono_error_ok (error))
8568 if (!type && abuilder->loaded_modules) {
8569 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8570 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8571 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8574 if (!mono_error_ok (error))
8583 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8587 MonoReflectionAssembly *assembly;
8591 if (image && image_is_dynamic (image))
8592 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8594 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8596 if (!mono_error_ok (&error))
8597 mono_error_raise_exception (&error); /* FIXME don't raise here */
8601 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8608 *type_resolve = TRUE;
8611 /* Reconstruct the type name */
8612 fullName = g_string_new ("");
8613 if (info->name_space && (info->name_space [0] != '\0'))
8614 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8616 g_string_printf (fullName, "%s", info->name);
8617 for (mod = info->nested; mod; mod = mod->next)
8618 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8620 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8621 mono_error_raise_exception (&error); /* FIXME don't raise here */
8624 if (assembly_is_dynamic (assembly->assembly))
8625 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8626 info, ignorecase, &error);
8628 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8629 info, ignorecase, &error);
8631 g_string_free (fullName, TRUE);
8632 if (!mono_error_ok (&error))
8633 mono_error_raise_exception (&error); /* FIXME don't raise here */
8638 mono_reflection_free_type_info (MonoTypeNameParse *info)
8640 g_list_free (info->modifiers);
8641 g_list_free (info->nested);
8643 if (info->type_arguments) {
8646 for (i = 0; i < info->type_arguments->len; i++) {
8647 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8649 mono_reflection_free_type_info (subinfo);
8650 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8654 g_ptr_array_free (info->type_arguments, TRUE);
8659 * mono_reflection_type_from_name:
8661 * @image: a metadata context (can be NULL).
8663 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8664 * it defaults to get the type from @image or, if @image is NULL or loading
8665 * from it fails, uses corlib.
8669 mono_reflection_type_from_name (char *name, MonoImage *image)
8671 MonoType *type = NULL;
8672 MonoTypeNameParse info;
8675 /* Make a copy since parse_type modifies its argument */
8676 tmp = g_strdup (name);
8678 /*g_print ("requested type %s\n", str);*/
8679 if (mono_reflection_parse_type (tmp, &info)) {
8680 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8684 mono_reflection_free_type_info (&info);
8689 * mono_reflection_get_token:
8691 * Return the metadata token of OBJ which should be an object
8692 * representing a metadata element.
8695 mono_reflection_get_token (MonoObject *obj)
8701 klass = obj->vtable->klass;
8703 if (strcmp (klass->name, "MethodBuilder") == 0) {
8704 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8706 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8707 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8708 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8710 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8711 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8712 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8714 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8715 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8716 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8717 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8718 } else if (strcmp (klass->name, "MonoType") == 0) {
8719 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8720 mono_error_raise_exception (&error); /* FIXME don't raise here */
8721 MonoClass *mc = mono_class_from_mono_type (type);
8722 if (!mono_class_init (mc))
8723 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8725 token = mc->type_token;
8726 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8727 strcmp (klass->name, "MonoMethod") == 0 ||
8728 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8729 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8730 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8731 if (m->method->is_inflated) {
8732 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8733 return inflated->declaring->token;
8735 token = m->method->token;
8737 } else if (strcmp (klass->name, "MonoField") == 0) {
8738 MonoReflectionField *f = (MonoReflectionField*)obj;
8740 if (is_field_on_inst (f->field)) {
8741 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8743 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8744 int field_index = f->field - dgclass->fields;
8747 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8748 obj = dgclass->field_objects [field_index];
8749 return mono_reflection_get_token (obj);
8752 token = mono_class_get_field_token (f->field);
8753 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8754 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8756 token = mono_class_get_property_token (p->property);
8757 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8758 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8760 token = mono_class_get_event_token (p->event);
8761 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8762 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8763 MonoClass *member_class = mono_object_class (p->MemberImpl);
8764 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8766 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8767 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8768 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8771 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8772 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8774 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8775 MonoException *ex = mono_get_exception_not_implemented (msg);
8777 mono_raise_exception (ex);
8784 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8788 int slen = mono_metadata_decode_value (p, &p);
8790 mono_error_init (error);
8792 n = (char *)g_memdup (p, slen + 1);
8794 t = mono_reflection_type_from_name (n, image);
8796 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8797 /* We don't free n, it's consumed by mono_error */
8798 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8804 return mono_class_from_mono_type (t);
8808 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8810 int slen, type = t->type;
8811 MonoClass *tklass = t->data.klass;
8813 mono_error_init (error);
8819 case MONO_TYPE_BOOLEAN: {
8820 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8825 case MONO_TYPE_CHAR:
8827 case MONO_TYPE_I2: {
8828 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8833 #if SIZEOF_VOID_P == 4
8839 case MONO_TYPE_I4: {
8840 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8845 #if SIZEOF_VOID_P == 8
8846 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8850 case MONO_TYPE_I8: {
8851 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8856 case MONO_TYPE_R8: {
8857 double *val = (double *)g_malloc (sizeof (double));
8862 case MONO_TYPE_VALUETYPE:
8863 if (t->data.klass->enumtype) {
8864 type = mono_class_enum_basetype (t->data.klass)->type;
8867 MonoClass *k = t->data.klass;
8869 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8870 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8876 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8879 case MONO_TYPE_STRING:
8880 if (*p == (char)0xFF) {
8884 slen = mono_metadata_decode_value (p, &p);
8886 return mono_string_new_len (mono_domain_get (), p, slen);
8887 case MONO_TYPE_CLASS: {
8888 MonoReflectionType *rt;
8891 if (*p == (char)0xFF) {
8896 slen = mono_metadata_decode_value (p, &p);
8897 n = (char *)g_memdup (p, slen + 1);
8899 t = mono_reflection_type_from_name (n, image);
8901 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8902 /* We don't free n, it's consumed by mono_error */
8903 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8909 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8910 if (!mono_error_ok (error))
8915 case MONO_TYPE_OBJECT: {
8918 MonoClass *subc = NULL;
8923 } else if (subt == 0x0E) {
8924 type = MONO_TYPE_STRING;
8926 } else if (subt == 0x1D) {
8927 MonoType simple_type = {{0}};
8931 type = MONO_TYPE_SZARRAY;
8932 if (etype == 0x50) {
8933 tklass = mono_defaults.systemtype_class;
8934 } else if (etype == 0x55) {
8935 tklass = load_cattr_enum_type (image, p, &p, error);
8936 if (!mono_error_ok (error))
8940 /* See Partition II, Appendix B3 */
8941 etype = MONO_TYPE_OBJECT;
8942 simple_type.type = (MonoTypeEnum)etype;
8943 tklass = mono_class_from_mono_type (&simple_type);
8946 } else if (subt == 0x55) {
8949 slen = mono_metadata_decode_value (p, &p);
8950 n = (char *)g_memdup (p, slen + 1);
8952 t = mono_reflection_type_from_name (n, image);
8954 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8955 /* We don't free n, it's consumed by mono_error */
8956 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8961 subc = mono_class_from_mono_type (t);
8962 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8963 MonoType simple_type = {{0}};
8964 simple_type.type = (MonoTypeEnum)subt;
8965 subc = mono_class_from_mono_type (&simple_type);
8967 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8969 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8971 if (mono_error_ok (error)) {
8972 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8973 g_assert (!subc->has_references);
8974 if (mono_error_ok (error))
8975 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8981 case MONO_TYPE_SZARRAY: {
8983 guint32 i, alen, basetype;
8986 if (alen == 0xffffffff) {
8990 arr = mono_array_new (mono_domain_get(), tklass, alen);
8991 basetype = tklass->byval_arg.type;
8992 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8993 basetype = mono_class_enum_basetype (tklass)->type;
8998 case MONO_TYPE_BOOLEAN:
8999 for (i = 0; i < alen; i++) {
9000 MonoBoolean val = *p++;
9001 mono_array_set (arr, MonoBoolean, i, val);
9004 case MONO_TYPE_CHAR:
9007 for (i = 0; i < alen; i++) {
9008 guint16 val = read16 (p);
9009 mono_array_set (arr, guint16, i, val);
9016 for (i = 0; i < alen; i++) {
9017 guint32 val = read32 (p);
9018 mono_array_set (arr, guint32, i, val);
9023 for (i = 0; i < alen; i++) {
9026 mono_array_set (arr, double, i, val);
9032 for (i = 0; i < alen; i++) {
9033 guint64 val = read64 (p);
9034 mono_array_set (arr, guint64, i, val);
9038 case MONO_TYPE_CLASS:
9039 case MONO_TYPE_OBJECT:
9040 case MONO_TYPE_STRING:
9041 case MONO_TYPE_SZARRAY:
9042 for (i = 0; i < alen; i++) {
9043 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9044 if (!mono_error_ok (error))
9046 mono_array_setref (arr, i, item);
9050 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9056 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9062 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9064 static MonoMethod *ctor;
9066 void *params [2], *unboxed;
9068 mono_error_init (error);
9071 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9073 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9074 return_val_if_nok (error, NULL);
9077 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9078 return_val_if_nok (error, NULL);
9079 unboxed = mono_object_unbox (retval);
9081 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9082 return_val_if_nok (error, NULL);
9088 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9090 static MonoMethod *ctor;
9092 void *unboxed, *params [2];
9094 mono_error_init (error);
9097 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9100 params [1] = typedarg;
9101 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9102 return_val_if_nok (error, NULL);
9104 unboxed = mono_object_unbox (retval);
9106 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9107 return_val_if_nok (error, NULL);
9113 type_is_reference (MonoType *type)
9115 switch (type->type) {
9116 case MONO_TYPE_BOOLEAN:
9117 case MONO_TYPE_CHAR:
9130 case MONO_TYPE_VALUETYPE:
9138 free_param_data (MonoMethodSignature *sig, void **params) {
9140 for (i = 0; i < sig->param_count; ++i) {
9141 if (!type_is_reference (sig->params [i]))
9142 g_free (params [i]);
9147 * Find the field index in the metadata FieldDef table.
9150 find_field_index (MonoClass *klass, MonoClassField *field) {
9153 for (i = 0; i < klass->field.count; ++i) {
9154 if (field == &klass->fields [i])
9155 return klass->field.first + 1 + i;
9161 * Find the property index in the metadata Property table.
9164 find_property_index (MonoClass *klass, MonoProperty *property) {
9167 for (i = 0; i < klass->ext->property.count; ++i) {
9168 if (property == &klass->ext->properties [i])
9169 return klass->ext->property.first + 1 + i;
9175 * Find the event index in the metadata Event table.
9178 find_event_index (MonoClass *klass, MonoEvent *event) {
9181 for (i = 0; i < klass->ext->event.count; ++i) {
9182 if (event == &klass->ext->events [i])
9183 return klass->ext->event.first + 1 + i;
9189 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9191 const char *p = (const char*)data;
9193 guint32 i, j, num_named;
9195 void *params_buf [32];
9196 void **params = NULL;
9197 MonoMethodSignature *sig;
9198 MonoObject *exc = NULL;
9200 mono_error_init (error);
9202 mono_class_init (method->klass);
9204 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9205 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9210 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9211 if (!mono_error_ok (error)) return NULL;
9213 mono_runtime_invoke_checked (method, attr, NULL, error);
9214 if (!mono_error_ok (error))
9220 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9223 /*g_print ("got attr %s\n", method->klass->name);*/
9225 sig = mono_method_signature (method);
9226 if (sig->param_count < 32) {
9227 params = params_buf;
9228 memset (params, 0, sizeof (void*) * sig->param_count);
9230 /* Allocate using GC so it gets GC tracking */
9231 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9236 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9237 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9238 if (!mono_error_ok (error))
9243 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9244 if (!mono_error_ok (error)) goto fail;
9246 mono_runtime_try_invoke (method, attr, params, &exc, error);
9247 if (!mono_error_ok (error))
9252 num_named = read16 (named);
9254 for (j = 0; j < num_named; j++) {
9256 char *name, named_type, data_type;
9257 named_type = *named++;
9258 data_type = *named++; /* type of data */
9259 if (data_type == MONO_TYPE_SZARRAY)
9260 data_type = *named++;
9261 if (data_type == MONO_TYPE_ENUM) {
9264 type_len = mono_metadata_decode_blob_size (named, &named);
9265 type_name = (char *)g_malloc (type_len + 1);
9266 memcpy (type_name, named, type_len);
9267 type_name [type_len] = 0;
9269 /* FIXME: lookup the type and check type consistency */
9272 name_len = mono_metadata_decode_blob_size (named, &named);
9273 name = (char *)g_malloc (name_len + 1);
9274 memcpy (name, named, name_len);
9275 name [name_len] = 0;
9277 if (named_type == 0x53) {
9278 MonoClassField *field;
9281 /* how this fail is a blackbox */
9282 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9284 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9289 val = load_cattr_value (image, field->type, named, &named, error);
9290 if (!mono_error_ok (error)) {
9292 if (!type_is_reference (field->type))
9297 mono_field_set_value (attr, field, val);
9298 if (!type_is_reference (field->type))
9300 } else if (named_type == 0x54) {
9303 MonoType *prop_type;
9305 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9308 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9314 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9319 /* can we have more that 1 arg in a custom attr named property? */
9320 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9321 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9323 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9324 if (!mono_error_ok (error)) {
9326 if (!type_is_reference (prop_type))
9327 g_free (pparams [0]);
9332 mono_property_set_value (prop, attr, pparams, NULL);
9333 if (!type_is_reference (prop_type))
9334 g_free (pparams [0]);
9339 free_param_data (method->signature, params);
9340 if (params != params_buf)
9341 mono_gc_free_fixed (params);
9346 free_param_data (method->signature, params);
9347 if (params != params_buf)
9348 mono_gc_free_fixed (params);
9350 mono_raise_exception ((MonoException*)exc);
9355 * mono_reflection_create_custom_attr_data_args:
9357 * Create an array of typed and named arguments from the cattr blob given by DATA.
9358 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9359 * NAMED_ARG_INFO will contain information about the named arguments.
9362 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)
9364 MonoArray *typedargs, *namedargs;
9365 MonoClass *attrklass;
9367 const char *p = (const char*)data;
9369 guint32 i, j, num_named;
9370 CattrNamedArg *arginfo = NULL;
9374 *named_arg_info = NULL;
9376 mono_error_init (error);
9378 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9379 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9383 mono_class_init (method->klass);
9385 domain = mono_domain_get ();
9387 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9390 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9394 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9398 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9399 if (!mono_error_ok (error)) {
9400 if (!type_is_reference (mono_method_signature (method)->params [i]))
9405 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9406 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9407 mono_array_setref (typedargs, i, obj);
9409 if (!type_is_reference (mono_method_signature (method)->params [i]))
9414 num_named = read16 (named);
9415 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9417 attrklass = method->klass;
9419 arginfo = g_new0 (CattrNamedArg, num_named);
9420 *named_arg_info = arginfo;
9422 for (j = 0; j < num_named; j++) {
9424 char *name, named_type, data_type;
9425 named_type = *named++;
9426 data_type = *named++; /* type of data */
9427 if (data_type == MONO_TYPE_SZARRAY)
9428 data_type = *named++;
9429 if (data_type == MONO_TYPE_ENUM) {
9432 type_len = mono_metadata_decode_blob_size (named, &named);
9433 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9436 type_name = (char *)g_malloc (type_len + 1);
9437 memcpy (type_name, named, type_len);
9438 type_name [type_len] = 0;
9440 /* FIXME: lookup the type and check type consistency */
9443 name_len = mono_metadata_decode_blob_size (named, &named);
9444 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9446 name = (char *)g_malloc (name_len + 1);
9447 memcpy (name, named, name_len);
9448 name [name_len] = 0;
9450 if (named_type == 0x53) {
9452 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9460 arginfo [j].type = field->type;
9461 arginfo [j].field = field;
9463 val = load_cattr_value (image, field->type, named, &named, error);
9464 if (!mono_error_ok (error)) {
9465 if (!type_is_reference (field->type))
9471 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9472 mono_array_setref (namedargs, j, obj);
9473 if (!type_is_reference (field->type))
9475 } else if (named_type == 0x54) {
9477 MonoType *prop_type;
9478 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9481 if (!prop || !prop->set) {
9486 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9487 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9489 arginfo [j].type = prop_type;
9490 arginfo [j].prop = prop;
9492 val = load_cattr_value (image, prop_type, named, &named, error);
9493 if (!mono_error_ok (error)) {
9494 if (!type_is_reference (prop_type))
9500 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9501 mono_array_setref (namedargs, j, obj);
9502 if (!type_is_reference (prop_type))
9508 *typed_args = typedargs;
9509 *named_args = namedargs;
9512 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9514 *named_arg_info = NULL;
9518 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9521 MonoArray *typedargs, *namedargs;
9524 CattrNamedArg *arginfo = NULL;
9528 mono_error_init (&error);
9536 image = assembly->assembly->image;
9537 method = ref_method->method;
9538 domain = mono_object_domain (ref_method);
9540 if (!mono_class_init (method->klass))
9541 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9543 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9544 if (!mono_error_ok (&error))
9547 if (mono_loader_get_last_error ()) {
9548 mono_error_set_from_loader_error (&error);
9552 if (!typedargs || !namedargs)
9555 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9556 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9557 MonoObject *typedarg;
9559 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9560 if (!is_ok (&error))
9562 mono_array_setref (typedargs, i, typedarg);
9565 for (i = 0; i < mono_array_length (namedargs); ++i) {
9566 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9567 MonoObject *typedarg, *namedarg, *minfo;
9569 if (arginfo [i].prop) {
9570 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9574 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9575 if (!mono_error_ok (&error))
9579 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9580 if (!is_ok (&error))
9582 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9583 if (!is_ok (&error))
9586 mono_array_setref (namedargs, i, namedarg);
9589 *ctor_args = typedargs;
9590 *named_args = namedargs;
9593 mono_error_raise_exception (&error);
9598 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9600 static MonoMethod *ctor;
9606 mono_error_init (error);
9608 g_assert (image->assembly);
9611 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9613 domain = mono_domain_get ();
9614 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9615 return_val_if_nok (error, NULL);
9616 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9617 return_val_if_nok (error, NULL);
9618 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9619 return_val_if_nok (error, NULL);
9620 params [2] = (gpointer)&cattr->data;
9621 params [3] = &cattr->data_size;
9623 mono_runtime_invoke_checked (ctor, attr, params, error);
9624 return_val_if_nok (error, NULL);
9629 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9635 mono_error_init (error);
9638 for (i = 0; i < cinfo->num_attrs; ++i) {
9639 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9643 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9645 for (i = 0; i < cinfo->num_attrs; ++i) {
9646 if (!cinfo->attrs [i].ctor) {
9647 /* The cattr type is not finished yet */
9648 /* We should include the type name but cinfo doesn't contain it */
9649 mono_error_set_type_load_name (error, NULL, NULL, "");
9652 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9653 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9654 if (!mono_error_ok (error))
9656 mono_array_setref (result, n, attr);
9664 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9667 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9668 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9674 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9680 mono_error_init (error);
9681 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9682 for (i = 0; i < cinfo->num_attrs; ++i) {
9683 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9684 return_val_if_nok (error, NULL);
9685 mono_array_setref (result, i, attr);
9691 * mono_custom_attrs_from_index:
9693 * Returns: NULL if no attributes are found or if a loading error occurs.
9696 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9699 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9700 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9704 * mono_custom_attrs_from_index_checked:
9706 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9709 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9711 guint32 mtoken, i, len;
9712 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9714 MonoCustomAttrInfo *ainfo;
9715 GList *tmp, *list = NULL;
9717 MonoCustomAttrEntry* attr;
9719 mono_error_init (error);
9721 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9723 i = mono_metadata_custom_attrs_from_index (image, idx);
9727 while (i < ca->rows) {
9728 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9730 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9733 len = g_list_length (list);
9736 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9737 ainfo->num_attrs = len;
9738 ainfo->image = image;
9739 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9740 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9741 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9742 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9743 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9744 mtoken |= MONO_TOKEN_METHOD_DEF;
9746 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9747 mtoken |= MONO_TOKEN_MEMBER_REF;
9750 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9753 attr = &ainfo->attrs [i - 1];
9754 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9756 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9762 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9763 /*FIXME raising an exception here doesn't make any sense*/
9764 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9769 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9770 attr->data_size = mono_metadata_decode_value (data, &data);
9771 attr->data = (guchar*)data;
9779 mono_custom_attrs_from_method (MonoMethod *method)
9782 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9783 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9788 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9792 mono_error_init (error);
9795 * An instantiated method has the same cattrs as the generic method definition.
9797 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9798 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9800 if (method->is_inflated)
9801 method = ((MonoMethodInflated *) method)->declaring;
9803 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9804 return lookup_custom_attr (method->klass->image, method);
9807 /* Synthetic methods */
9810 idx = mono_method_get_index (method);
9811 idx <<= MONO_CUSTOM_ATTR_BITS;
9812 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9813 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9817 mono_custom_attrs_from_class (MonoClass *klass)
9820 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9821 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9826 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9830 mono_error_init (error);
9832 if (klass->generic_class)
9833 klass = klass->generic_class->container_class;
9835 if (image_is_dynamic (klass->image))
9836 return lookup_custom_attr (klass->image, klass);
9838 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9839 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9840 idx <<= MONO_CUSTOM_ATTR_BITS;
9841 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9843 idx = mono_metadata_token_index (klass->type_token);
9844 idx <<= MONO_CUSTOM_ATTR_BITS;
9845 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9847 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9851 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9854 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9855 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9860 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9864 mono_error_init (error);
9866 if (image_is_dynamic (assembly->image))
9867 return lookup_custom_attr (assembly->image, assembly);
9868 idx = 1; /* there is only one assembly */
9869 idx <<= MONO_CUSTOM_ATTR_BITS;
9870 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9871 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9874 static MonoCustomAttrInfo*
9875 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9879 if (image_is_dynamic (image))
9880 return lookup_custom_attr (image, image);
9881 idx = 1; /* there is only one module */
9882 idx <<= MONO_CUSTOM_ATTR_BITS;
9883 idx |= MONO_CUSTOM_ATTR_MODULE;
9884 return mono_custom_attrs_from_index_checked (image, idx, error);
9888 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9891 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9892 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9897 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9901 if (image_is_dynamic (klass->image)) {
9902 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9903 return lookup_custom_attr (klass->image, property);
9905 idx = find_property_index (klass, property);
9906 idx <<= MONO_CUSTOM_ATTR_BITS;
9907 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9908 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9912 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9915 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9916 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9921 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9925 if (image_is_dynamic (klass->image)) {
9926 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9927 return lookup_custom_attr (klass->image, event);
9929 idx = find_event_index (klass, event);
9930 idx <<= MONO_CUSTOM_ATTR_BITS;
9931 idx |= MONO_CUSTOM_ATTR_EVENT;
9932 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9936 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9939 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9940 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9945 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9948 mono_error_init (error);
9950 if (image_is_dynamic (klass->image)) {
9951 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9952 return lookup_custom_attr (klass->image, field);
9954 idx = find_field_index (klass, field);
9955 idx <<= MONO_CUSTOM_ATTR_BITS;
9956 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9957 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9961 * mono_custom_attrs_from_param:
9962 * @method: handle to the method that we want to retrieve custom parameter information from
9963 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9965 * The result must be released with mono_custom_attrs_free().
9967 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9970 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9973 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9974 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9979 * mono_custom_attrs_from_param_checked:
9980 * @method: handle to the method that we want to retrieve custom parameter information from
9981 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9982 * @error: set on error
9984 * The result must be released with mono_custom_attrs_free().
9986 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9989 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9992 guint32 i, idx, method_index;
9993 guint32 param_list, param_last, param_pos, found;
9995 MonoReflectionMethodAux *aux;
9997 mono_error_init (error);
10000 * An instantiated method has the same cattrs as the generic method definition.
10002 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10003 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10005 if (method->is_inflated)
10006 method = ((MonoMethodInflated *) method)->declaring;
10008 if (image_is_dynamic (method->klass->image)) {
10009 MonoCustomAttrInfo *res, *ainfo;
10012 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10013 if (!aux || !aux->param_cattr)
10016 /* Need to copy since it will be freed later */
10017 ainfo = aux->param_cattr [param];
10020 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10021 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10022 memcpy (res, ainfo, size);
10026 image = method->klass->image;
10027 method_index = mono_method_get_index (method);
10030 ca = &image->tables [MONO_TABLE_METHOD];
10032 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10033 if (method_index == ca->rows) {
10034 ca = &image->tables [MONO_TABLE_PARAM];
10035 param_last = ca->rows + 1;
10037 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10038 ca = &image->tables [MONO_TABLE_PARAM];
10041 for (i = param_list; i < param_last; ++i) {
10042 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10043 if (param_pos == param) {
10051 idx <<= MONO_CUSTOM_ATTR_BITS;
10052 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10053 return mono_custom_attrs_from_index_checked (image, idx, error);
10057 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10061 for (i = 0; i < ainfo->num_attrs; ++i) {
10062 klass = ainfo->attrs [i].ctor->klass;
10063 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10070 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10073 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10074 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10079 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10085 mono_error_init (error);
10088 for (i = 0; i < ainfo->num_attrs; ++i) {
10089 klass = ainfo->attrs [i].ctor->klass;
10090 if (mono_class_has_parent (klass, attr_klass)) {
10095 if (attr_index == -1)
10098 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10099 if (!mono_error_ok (error))
10101 return mono_array_get (attrs, MonoObject*, attr_index);
10105 * mono_reflection_get_custom_attrs_info:
10106 * @obj: a reflection object handle
10108 * Return the custom attribute info for attributes defined for the
10109 * reflection handle @obj. The objects.
10111 * FIXME this function leaks like a sieve for SRE objects.
10113 MonoCustomAttrInfo*
10114 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10117 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10118 mono_error_assert_ok (&error);
10123 * mono_reflection_get_custom_attrs_info_checked:
10124 * @obj: a reflection object handle
10125 * @error: set on error
10127 * Return the custom attribute info for attributes defined for the
10128 * reflection handle @obj. The objects.
10130 * On failure returns NULL and sets @error.
10132 * FIXME this function leaks like a sieve for SRE objects.
10134 MonoCustomAttrInfo*
10135 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10138 MonoCustomAttrInfo *cinfo = NULL;
10140 mono_error_init (error);
10142 klass = obj->vtable->klass;
10143 if (klass == mono_defaults.monotype_class) {
10144 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10145 return_val_if_nok (error, NULL);
10146 klass = mono_class_from_mono_type (type);
10147 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10148 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10149 return_val_if_nok (error, NULL);
10150 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10151 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10152 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10153 return_val_if_nok (error, NULL);
10154 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10155 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10156 cinfo = mono_custom_attrs_from_module (module->image, error);
10157 return_val_if_nok (error, NULL);
10158 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10159 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10160 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10161 return_val_if_nok (error, NULL);
10162 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10163 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10164 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10165 return_val_if_nok (error, NULL);
10166 } else if (strcmp ("MonoField", klass->name) == 0) {
10167 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10168 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10169 return_val_if_nok (error, NULL);
10170 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10171 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10172 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10173 return_val_if_nok (error, NULL);
10174 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10175 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10176 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10177 return_val_if_nok (error, NULL);
10178 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10179 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10180 MonoClass *member_class = mono_object_class (param->MemberImpl);
10181 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10182 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10183 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10184 return_val_if_nok (error, NULL);
10185 } else if (is_sr_mono_property (member_class)) {
10186 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10187 MonoMethod *method;
10188 if (!(method = prop->property->get))
10189 method = prop->property->set;
10192 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10193 return_val_if_nok (error, NULL);
10195 #ifndef DISABLE_REFLECTION_EMIT
10196 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10197 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10198 return_val_if_nok (error, NULL);
10199 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10200 return_val_if_nok (error, NULL);
10201 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10202 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10203 MonoMethod *method = NULL;
10204 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10205 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10206 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10207 method = ((MonoReflectionMethod *)c->cb)->method;
10209 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));
10211 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10212 return_val_if_nok (error, NULL);
10216 char *type_name = mono_type_get_full_name (member_class);
10217 mono_error_set_generic_error (error, "System", "NotSupportedException",
10218 "Custom attributes on a ParamInfo with member %s are not supported",
10220 g_free (type_name);
10223 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10224 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10225 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10226 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10227 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10228 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10229 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10230 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10231 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10232 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10233 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10234 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10235 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10236 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10237 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10238 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10239 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10240 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10241 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10242 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10243 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10244 return_val_if_nok (error, NULL);
10245 } else { /* handle other types here... */
10246 g_error ("get custom attrs not yet supported for %s", klass->name);
10253 * mono_reflection_get_custom_attrs_by_type:
10254 * @obj: a reflection object handle
10256 * Return an array with all the custom attributes defined of the
10257 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10258 * of that type are returned. The objects are fully build. Return NULL if a loading error
10262 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10265 MonoCustomAttrInfo *cinfo;
10267 mono_error_init (error);
10269 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10270 return_val_if_nok (error, NULL);
10272 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10275 if (!cinfo->cached)
10276 mono_custom_attrs_free (cinfo);
10278 mono_loader_assert_no_error ();
10279 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10286 * mono_reflection_get_custom_attrs:
10287 * @obj: a reflection object handle
10289 * Return an array with all the custom attributes defined of the
10290 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10294 mono_reflection_get_custom_attrs (MonoObject *obj)
10298 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10302 * mono_reflection_get_custom_attrs_data:
10303 * @obj: a reflection obj handle
10305 * Returns an array of System.Reflection.CustomAttributeData,
10306 * which include information about attributes reflected on
10307 * types loaded using the Reflection Only methods
10310 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10314 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10315 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10320 * mono_reflection_get_custom_attrs_data_checked:
10321 * @obj: a reflection obj handle
10322 * @error: set on error
10324 * Returns an array of System.Reflection.CustomAttributeData,
10325 * which include information about attributes reflected on
10326 * types loaded using the Reflection Only methods
10329 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10332 MonoCustomAttrInfo *cinfo;
10334 mono_error_init (error);
10336 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10337 return_val_if_nok (error, NULL);
10339 result = mono_custom_attrs_data_construct (cinfo, error);
10340 return_val_if_nok (error, NULL);
10341 if (!cinfo->cached)
10342 mono_custom_attrs_free (cinfo);
10344 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10346 if (mono_loader_get_last_error ())
10347 mono_error_set_from_loader_error (error);
10352 static MonoReflectionType*
10353 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10355 static MonoMethod *method_get_underlying_system_type = NULL;
10356 MonoReflectionType *rt;
10357 MonoMethod *usertype_method;
10359 mono_error_init (error);
10361 if (!method_get_underlying_system_type)
10362 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10364 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10366 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10373 is_corlib_type (MonoClass *klass)
10375 return klass->image == mono_defaults.corlib;
10378 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10379 static MonoClass *cached_class; \
10380 if (cached_class) \
10381 return cached_class == _class; \
10382 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10383 cached_class = _class; \
10390 #ifndef DISABLE_REFLECTION_EMIT
10392 is_sre_array (MonoClass *klass)
10394 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10398 is_sre_byref (MonoClass *klass)
10400 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10404 is_sre_pointer (MonoClass *klass)
10406 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10410 is_sre_generic_instance (MonoClass *klass)
10412 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10416 is_sre_type_builder (MonoClass *klass)
10418 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10422 is_sre_method_builder (MonoClass *klass)
10424 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10428 is_sre_ctor_builder (MonoClass *klass)
10430 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10434 is_sre_field_builder (MonoClass *klass)
10436 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10440 is_sre_method_on_tb_inst (MonoClass *klass)
10442 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10446 is_sre_ctor_on_tb_inst (MonoClass *klass)
10448 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10452 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10455 mono_error_init (error);
10462 if (is_usertype (ref)) {
10463 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10464 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10470 klass = mono_object_class (ref);
10472 if (is_sre_array (klass)) {
10474 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10475 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10476 return_val_if_nok (error, NULL);
10478 if (sre_array->rank == 0) //single dimentional array
10479 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10481 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10482 sre_array->type.type = res;
10484 } else if (is_sre_byref (klass)) {
10486 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10487 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10488 return_val_if_nok (error, NULL);
10490 res = &mono_class_from_mono_type (base)->this_arg;
10491 sre_byref->type.type = res;
10493 } else if (is_sre_pointer (klass)) {
10495 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10496 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10497 return_val_if_nok (error, NULL);
10499 res = &mono_ptr_class_get (base)->byval_arg;
10500 sre_pointer->type.type = res;
10502 } else if (is_sre_generic_instance (klass)) {
10503 MonoType *res, **types;
10504 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10507 count = mono_array_length (gclass->type_arguments);
10508 types = g_new0 (MonoType*, count);
10509 for (i = 0; i < count; ++i) {
10510 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10511 types [i] = mono_reflection_type_get_handle (t, error);
10512 if (!types[i] || !is_ok (error)) {
10518 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10521 gclass->type.type = res;
10525 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10530 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10533 mono_reflection_type_get_handle (type, &error);
10534 mono_error_set_pending_exception (&error);
10538 mono_reflection_register_with_runtime (MonoReflectionType *type)
10541 MonoType *res = mono_reflection_type_get_handle (type, &error);
10542 mono_error_raise_exception (&error); /* FIXME don't raise here */
10543 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10547 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10549 klass = mono_class_from_mono_type (res);
10551 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10552 mono_domain_lock (domain);
10554 if (!image_is_dynamic (klass->image)) {
10555 mono_class_setup_supertypes (klass);
10557 if (!domain->type_hash)
10558 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10559 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10560 mono_g_hash_table_insert (domain->type_hash, res, type);
10562 mono_domain_unlock (domain);
10563 mono_loader_unlock ();
10567 * LOCKING: Assumes the loader lock is held.
10569 static MonoMethodSignature*
10570 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10572 MonoMethodSignature *sig;
10575 count = parameters? mono_array_length (parameters): 0;
10577 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10578 sig->param_count = count;
10579 sig->sentinelpos = -1; /* FIXME */
10580 for (i = 0; i < count; ++i) {
10581 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10582 mono_error_raise_exception (&error); /* FIXME don't raise here */
10588 * LOCKING: Assumes the loader lock is held.
10590 static MonoMethodSignature*
10591 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10592 MonoMethodSignature *sig;
10594 sig = parameters_to_signature (image, ctor->parameters);
10595 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10596 sig->ret = &mono_defaults.void_class->byval_arg;
10601 * LOCKING: Assumes the loader lock is held.
10603 static MonoMethodSignature*
10604 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10606 MonoMethodSignature *sig;
10608 sig = parameters_to_signature (image, method->parameters);
10609 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10610 if (method->rtype) {
10611 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10612 mono_error_raise_exception (&error); /* FIXME don't raise here */
10614 sig->ret = &mono_defaults.void_class->byval_arg;
10616 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10620 static MonoMethodSignature*
10621 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10623 MonoMethodSignature *sig;
10625 sig = parameters_to_signature (NULL, method->parameters);
10626 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10627 if (method->rtype) {
10628 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10629 mono_error_raise_exception (&error); /* FIXME don't raise here */
10631 sig->ret = &mono_defaults.void_class->byval_arg;
10633 sig->generic_param_count = 0;
10638 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10641 MonoClass *klass = mono_object_class (prop);
10642 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10643 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10644 *name = mono_string_to_utf8 (pb->name);
10645 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10646 mono_error_raise_exception (&error); /* FIXME don't raise here */
10648 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10649 *name = g_strdup (p->property->name);
10650 if (p->property->get)
10651 *type = mono_method_signature (p->property->get)->ret;
10653 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10658 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10661 MonoClass *klass = mono_object_class (field);
10662 if (strcmp (klass->name, "FieldBuilder") == 0) {
10663 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10664 *name = mono_string_to_utf8 (fb->name);
10665 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10666 mono_error_raise_exception (&error); /* FIXME don't raise here */
10668 MonoReflectionField *f = (MonoReflectionField *)field;
10669 *name = g_strdup (mono_field_get_name (f->field));
10670 *type = f->field->type;
10674 #else /* DISABLE_REFLECTION_EMIT */
10677 mono_reflection_register_with_runtime (MonoReflectionType *type)
10679 /* This is empty */
10683 is_sre_type_builder (MonoClass *klass)
10689 is_sre_generic_instance (MonoClass *klass)
10695 init_type_builder_generics (MonoObject *type)
10699 #endif /* !DISABLE_REFLECTION_EMIT */
10703 is_sr_mono_field (MonoClass *klass)
10705 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10709 is_sr_mono_property (MonoClass *klass)
10711 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10715 is_sr_mono_method (MonoClass *klass)
10717 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10721 is_sr_mono_cmethod (MonoClass *klass)
10723 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10727 is_sr_mono_generic_method (MonoClass *klass)
10729 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10733 is_sr_mono_generic_cmethod (MonoClass *klass)
10735 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10739 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10741 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10745 is_usertype (MonoReflectionType *ref)
10747 MonoClass *klass = mono_object_class (ref);
10748 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10751 static MonoReflectionType*
10752 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10754 mono_error_init (error);
10755 if (!type || type->type)
10758 if (is_usertype (type)) {
10759 type = mono_reflection_type_get_underlying_system_type (type, error);
10760 return_val_if_nok (error, NULL);
10761 if (is_usertype (type)) {
10762 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10770 * Encode a value in a custom attribute stream of bytes.
10771 * The value to encode is either supplied as an object in argument val
10772 * (valuetypes are boxed), or as a pointer to the data in the
10774 * @type represents the type of the value
10775 * @buffer is the start of the buffer
10776 * @p the current position in the buffer
10777 * @buflen contains the size of the buffer and is used to return the new buffer size
10778 * if this needs to be realloced.
10779 * @retbuffer and @retp return the start and the position of the buffer
10782 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10785 MonoTypeEnum simple_type;
10787 if ((p-buffer) + 10 >= *buflen) {
10790 newbuf = (char *)g_realloc (buffer, *buflen);
10791 p = newbuf + (p-buffer);
10795 argval = ((char*)arg + sizeof (MonoObject));
10796 simple_type = type->type;
10798 switch (simple_type) {
10799 case MONO_TYPE_BOOLEAN:
10804 case MONO_TYPE_CHAR:
10807 swap_with_size (p, argval, 2, 1);
10813 swap_with_size (p, argval, 4, 1);
10817 swap_with_size (p, argval, 8, 1);
10822 swap_with_size (p, argval, 8, 1);
10825 case MONO_TYPE_VALUETYPE:
10826 if (type->data.klass->enumtype) {
10827 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10830 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10833 case MONO_TYPE_STRING: {
10840 str = mono_string_to_utf8 ((MonoString*)arg);
10841 slen = strlen (str);
10842 if ((p-buffer) + 10 + slen >= *buflen) {
10846 newbuf = (char *)g_realloc (buffer, *buflen);
10847 p = newbuf + (p-buffer);
10850 mono_metadata_encode_value (slen, p, &p);
10851 memcpy (p, str, slen);
10856 case MONO_TYPE_CLASS: {
10859 MonoType *arg_type;
10865 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10866 mono_error_raise_exception (&error); /* FIXME don't raise here */
10867 str = type_get_qualified_name (arg_type, NULL);
10868 slen = strlen (str);
10869 if ((p-buffer) + 10 + slen >= *buflen) {
10873 newbuf = (char *)g_realloc (buffer, *buflen);
10874 p = newbuf + (p-buffer);
10877 mono_metadata_encode_value (slen, p, &p);
10878 memcpy (p, str, slen);
10883 case MONO_TYPE_SZARRAY: {
10885 MonoClass *eclass, *arg_eclass;
10888 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10891 len = mono_array_length ((MonoArray*)arg);
10893 *p++ = (len >> 8) & 0xff;
10894 *p++ = (len >> 16) & 0xff;
10895 *p++ = (len >> 24) & 0xff;
10897 *retbuffer = buffer;
10898 eclass = type->data.klass;
10899 arg_eclass = mono_object_class (arg)->element_class;
10902 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10903 eclass = mono_defaults.object_class;
10905 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10906 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10907 int elsize = mono_class_array_element_size (arg_eclass);
10908 for (i = 0; i < len; ++i) {
10909 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10912 } else if (eclass->valuetype && arg_eclass->valuetype) {
10913 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10914 int elsize = mono_class_array_element_size (eclass);
10915 for (i = 0; i < len; ++i) {
10916 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10920 for (i = 0; i < len; ++i) {
10921 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10926 case MONO_TYPE_OBJECT: {
10932 * The parameter type is 'object' but the type of the actual
10933 * argument is not. So we have to add type information to the blob
10934 * too. This is completely undocumented in the spec.
10938 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10943 klass = mono_object_class (arg);
10945 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10948 } else if (klass->enumtype) {
10950 } else if (klass == mono_defaults.string_class) {
10951 simple_type = MONO_TYPE_STRING;
10954 } else if (klass->rank == 1) {
10956 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10957 /* See Partition II, Appendix B3 */
10960 *p++ = klass->element_class->byval_arg.type;
10961 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10963 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10964 *p++ = simple_type = klass->byval_arg.type;
10967 g_error ("unhandled type in custom attr");
10969 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10970 slen = strlen (str);
10971 if ((p-buffer) + 10 + slen >= *buflen) {
10975 newbuf = (char *)g_realloc (buffer, *buflen);
10976 p = newbuf + (p-buffer);
10979 mono_metadata_encode_value (slen, p, &p);
10980 memcpy (p, str, slen);
10983 simple_type = mono_class_enum_basetype (klass)->type;
10987 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10990 *retbuffer = buffer;
10994 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10996 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10997 char *str = type_get_qualified_name (type, NULL);
10998 int slen = strlen (str);
11002 * This seems to be optional...
11005 mono_metadata_encode_value (slen, p, &p);
11006 memcpy (p, str, slen);
11009 } else if (type->type == MONO_TYPE_OBJECT) {
11011 } else if (type->type == MONO_TYPE_CLASS) {
11012 /* it should be a type: encode_cattr_value () has the check */
11015 mono_metadata_encode_value (type->type, p, &p);
11016 if (type->type == MONO_TYPE_SZARRAY)
11017 /* See the examples in Partition VI, Annex B */
11018 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11024 #ifndef DISABLE_REFLECTION_EMIT
11026 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11029 /* Preallocate a large enough buffer */
11030 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11031 char *str = type_get_qualified_name (type, NULL);
11032 len = strlen (str);
11034 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11035 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11036 len = strlen (str);
11041 len += strlen (name);
11043 if ((p-buffer) + 20 + len >= *buflen) {
11047 newbuf = (char *)g_realloc (buffer, *buflen);
11048 p = newbuf + (p-buffer);
11052 encode_field_or_prop_type (type, p, &p);
11054 len = strlen (name);
11055 mono_metadata_encode_value (len, p, &p);
11056 memcpy (p, name, len);
11058 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11060 *retbuffer = buffer;
11064 * mono_reflection_get_custom_attrs_blob:
11065 * @ctor: custom attribute constructor
11066 * @ctorArgs: arguments o the constructor
11072 * Creates the blob of data that needs to be saved in the metadata and that represents
11073 * the custom attributed described by @ctor, @ctorArgs etc.
11074 * Returns: a Byte array representing the blob of data.
11077 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11080 MonoMethodSignature *sig;
11085 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11086 /* sig is freed later so allocate it in the heap */
11087 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11089 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11092 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11094 p = buffer = (char *)g_malloc (buflen);
11095 /* write the prolog */
11098 for (i = 0; i < sig->param_count; ++i) {
11099 arg = mono_array_get (ctorArgs, MonoObject*, i);
11100 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11104 i += mono_array_length (properties);
11106 i += mono_array_length (fields);
11108 *p++ = (i >> 8) & 0xff;
11111 for (i = 0; i < mono_array_length (properties); ++i) {
11115 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11116 get_prop_name_and_type (prop, &pname, &ptype);
11117 *p++ = 0x54; /* PROPERTY signature */
11118 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11125 for (i = 0; i < mono_array_length (fields); ++i) {
11129 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11130 get_field_name_and_type (field, &fname, &ftype);
11131 *p++ = 0x53; /* FIELD signature */
11132 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11137 g_assert (p - buffer <= buflen);
11138 buflen = p - buffer;
11139 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11140 p = mono_array_addr (result, char, 0);
11141 memcpy (p, buffer, buflen);
11143 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11149 * mono_reflection_setup_internal_class:
11150 * @tb: a TypeBuilder object
11152 * Creates a MonoClass that represents the TypeBuilder.
11153 * This is a trick that lets us simplify a lot of reflection code
11154 * (and will allow us to support Build and Run assemblies easier).
11157 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11160 MonoClass *klass, *parent;
11162 RESOLVE_TYPE (tb->parent, &error);
11163 mono_error_raise_exception (&error); /* FIXME don't raise here */
11165 mono_loader_lock ();
11168 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11169 if (!is_ok (&error)) {
11170 mono_loader_unlock ();
11171 mono_error_raise_exception (&error); /* FIXME don't raise here */
11173 /* check so we can compile corlib correctly */
11174 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11175 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11176 parent = parent_type->data.klass;
11178 parent = mono_class_from_mono_type (parent_type);
11184 /* the type has already being created: it means we just have to change the parent */
11185 if (tb->type.type) {
11186 klass = mono_class_from_mono_type (tb->type.type);
11187 klass->parent = NULL;
11188 /* fool mono_class_setup_parent */
11189 klass->supertypes = NULL;
11190 mono_class_setup_parent (klass, parent);
11191 mono_class_setup_mono_type (klass);
11192 mono_loader_unlock ();
11196 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11198 klass->image = &tb->module->dynamic_image->image;
11200 klass->inited = 1; /* we lie to the runtime */
11201 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11202 if (!mono_error_ok (&error))
11204 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11205 if (!mono_error_ok (&error))
11207 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11208 klass->flags = tb->attrs;
11210 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11212 klass->element_class = klass;
11214 if (mono_class_get_ref_info (klass) == NULL) {
11216 mono_class_set_ref_info (klass, tb);
11218 /* Put into cache so mono_class_get_checked () will find it.
11219 Skip nested types as those should not be available on the global scope. */
11220 if (!tb->nesting_type)
11221 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11224 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11225 by performing a mono_class_get which does the full resolution.
11227 Working around this semantics would require us to write a lot of code for no clear advantage.
11229 mono_image_append_class_to_reflection_info_set (klass);
11231 g_assert (mono_class_get_ref_info (klass) == tb);
11234 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11236 if (parent != NULL) {
11237 mono_class_setup_parent (klass, parent);
11238 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11239 const char *old_n = klass->name;
11240 /* trick to get relative numbering right when compiling corlib */
11241 klass->name = "BuildingObject";
11242 mono_class_setup_parent (klass, mono_defaults.object_class);
11243 klass->name = old_n;
11246 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11247 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11248 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11249 klass->instance_size = sizeof (MonoObject);
11250 klass->size_inited = 1;
11251 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11254 mono_class_setup_mono_type (klass);
11256 mono_class_setup_supertypes (klass);
11259 * FIXME: handle interfaces.
11262 tb->type.type = &klass->byval_arg;
11264 if (tb->nesting_type) {
11265 g_assert (tb->nesting_type->type);
11266 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11267 if (!is_ok (&error)) goto failure;
11268 klass->nested_in = mono_class_from_mono_type (nesting_type);
11271 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11273 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11275 mono_loader_unlock ();
11279 mono_loader_unlock ();
11280 mono_error_raise_exception (&error);
11284 * mono_reflection_setup_generic_class:
11285 * @tb: a TypeBuilder object
11287 * Setup the generic class before adding the first generic parameter.
11290 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11295 * mono_reflection_create_generic_class:
11296 * @tb: a TypeBuilder object
11298 * Creates the generic class after all generic parameters have been added.
11301 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11307 klass = mono_class_from_mono_type (tb->type.type);
11309 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11311 if (klass->generic_container || (count == 0))
11314 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11316 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11318 klass->generic_container->owner.klass = klass;
11319 klass->generic_container->type_argc = count;
11320 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11322 klass->is_generic = 1;
11324 for (i = 0; i < count; i++) {
11325 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11326 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11327 mono_error_raise_exception (&error); /* FIXME don't raise here */
11328 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11329 klass->generic_container->type_params [i] = *param;
11330 /*Make sure we are a diferent type instance */
11331 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11332 klass->generic_container->type_params [i].info.pklass = NULL;
11333 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11335 g_assert (klass->generic_container->type_params [i].param.owner);
11338 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11342 * mono_reflection_create_internal_class:
11343 * @tb: a TypeBuilder object
11345 * Actually create the MonoClass that is associated with the TypeBuilder.
11348 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11353 klass = mono_class_from_mono_type (tb->type.type);
11355 mono_loader_lock ();
11356 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11357 MonoReflectionFieldBuilder *fb;
11359 MonoType *enum_basetype;
11361 g_assert (tb->fields != NULL);
11362 g_assert (mono_array_length (tb->fields) >= 1);
11364 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11366 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11367 if (!is_ok (&error)) {
11368 mono_loader_unlock ();
11369 mono_error_raise_exception (&error); /* FIXME don't raise here */
11371 if (!mono_type_is_valid_enum_basetype (field_type)) {
11372 mono_loader_unlock ();
11376 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11377 if (!is_ok (&error)) {
11378 mono_loader_unlock ();
11379 mono_error_raise_exception (&error); /* FIXME don't raise here */
11381 klass->element_class = mono_class_from_mono_type (enum_basetype);
11382 if (!klass->element_class)
11383 klass->element_class = mono_class_from_mono_type (enum_basetype);
11386 * get the element_class from the current corlib.
11388 ec = default_class_from_mono_type (enum_basetype);
11389 klass->instance_size = ec->instance_size;
11390 klass->size_inited = 1;
11392 * this is almost safe to do with enums and it's needed to be able
11393 * to create objects of the enum type (for use in SetConstant).
11395 /* FIXME: Does this mean enums can't have method overrides ? */
11396 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11398 mono_loader_unlock ();
11401 static MonoMarshalSpec*
11402 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11403 MonoReflectionMarshal *minfo)
11406 MonoMarshalSpec *res;
11408 res = image_g_new0 (image, MonoMarshalSpec, 1);
11409 res->native = (MonoMarshalNative)minfo->type;
11411 switch (minfo->type) {
11412 case MONO_NATIVE_LPARRAY:
11413 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11414 if (minfo->has_size) {
11415 res->data.array_data.param_num = minfo->param_num;
11416 res->data.array_data.num_elem = minfo->count;
11417 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11420 res->data.array_data.param_num = -1;
11421 res->data.array_data.num_elem = -1;
11422 res->data.array_data.elem_mult = -1;
11426 case MONO_NATIVE_BYVALTSTR:
11427 case MONO_NATIVE_BYVALARRAY:
11428 res->data.array_data.num_elem = minfo->count;
11431 case MONO_NATIVE_CUSTOM:
11432 if (minfo->marshaltyperef) {
11433 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11434 mono_error_raise_exception (&error); /* FIXME don't raise here */
11435 res->data.custom_data.custom_name =
11436 type_get_fully_qualified_name (marshaltyperef);
11438 if (minfo->mcookie)
11439 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11448 #endif /* !DISABLE_REFLECTION_EMIT */
11450 MonoReflectionMarshalAsAttribute*
11451 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11452 MonoMarshalSpec *spec, MonoError *error)
11454 MonoReflectionType *rt;
11455 MonoReflectionMarshalAsAttribute *minfo;
11458 mono_error_init (error);
11460 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11463 minfo->utype = spec->native;
11465 switch (minfo->utype) {
11466 case MONO_NATIVE_LPARRAY:
11467 minfo->array_subtype = spec->data.array_data.elem_type;
11468 minfo->size_const = spec->data.array_data.num_elem;
11469 if (spec->data.array_data.param_num != -1)
11470 minfo->size_param_index = spec->data.array_data.param_num;
11473 case MONO_NATIVE_BYVALTSTR:
11474 case MONO_NATIVE_BYVALARRAY:
11475 minfo->size_const = spec->data.array_data.num_elem;
11478 case MONO_NATIVE_CUSTOM:
11479 if (spec->data.custom_data.custom_name) {
11480 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11482 rt = mono_type_get_object_checked (domain, mtype, error);
11486 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11489 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11491 if (spec->data.custom_data.cookie)
11492 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11502 #ifndef DISABLE_REFLECTION_EMIT
11504 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11505 ReflectionMethodBuilder *rmb,
11506 MonoMethodSignature *sig)
11510 MonoMethodWrapper *wrapperm;
11511 MonoMarshalSpec **specs;
11512 MonoReflectionMethodAux *method_aux;
11517 mono_error_init (&error);
11519 * Methods created using a MethodBuilder should have their memory allocated
11520 * inside the image mempool, while dynamic methods should have their memory
11523 dynamic = rmb->refs != NULL;
11524 image = dynamic ? NULL : klass->image;
11527 g_assert (!klass->generic_class);
11529 mono_loader_lock ();
11531 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11532 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11533 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11535 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11537 wrapperm = (MonoMethodWrapper*)m;
11539 m->dynamic = dynamic;
11541 m->flags = rmb->attrs;
11542 m->iflags = rmb->iattrs;
11543 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11545 m->signature = sig;
11546 m->sre_method = TRUE;
11547 m->skip_visibility = rmb->skip_visibility;
11548 if (rmb->table_idx)
11549 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11551 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11552 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11553 m->string_ctor = 1;
11555 m->signature->pinvoke = 1;
11556 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11557 m->signature->pinvoke = 1;
11559 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11561 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11562 g_assert (mono_error_ok (&error));
11563 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11564 g_assert (mono_error_ok (&error));
11566 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11568 if (image_is_dynamic (klass->image))
11569 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11571 mono_loader_unlock ();
11574 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11575 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11576 MonoMethodHeader *header;
11578 gint32 max_stack, i;
11579 gint32 num_locals = 0;
11580 gint32 num_clauses = 0;
11584 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11585 code_size = rmb->ilgen->code_len;
11586 max_stack = rmb->ilgen->max_stack;
11587 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11588 if (rmb->ilgen->ex_handlers)
11589 num_clauses = method_count_clauses (rmb->ilgen);
11592 code = mono_array_addr (rmb->code, guint8, 0);
11593 code_size = mono_array_length (rmb->code);
11594 /* we probably need to run a verifier on the code... */
11604 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11605 header->code_size = code_size;
11606 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11607 memcpy ((char*)header->code, code, code_size);
11608 header->max_stack = max_stack;
11609 header->init_locals = rmb->init_locals;
11610 header->num_locals = num_locals;
11612 for (i = 0; i < num_locals; ++i) {
11613 MonoReflectionLocalBuilder *lb =
11614 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11616 header->locals [i] = image_g_new0 (image, MonoType, 1);
11617 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11618 mono_error_assert_ok (&error);
11619 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11622 header->num_clauses = num_clauses;
11624 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11625 rmb->ilgen, num_clauses, &error);
11626 mono_error_assert_ok (&error);
11629 wrapperm->header = header;
11632 if (rmb->generic_params) {
11633 int count = mono_array_length (rmb->generic_params);
11634 MonoGenericContainer *container = rmb->generic_container;
11636 g_assert (container);
11638 container->type_argc = count;
11639 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11640 container->owner.method = m;
11641 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11643 m->is_generic = TRUE;
11644 mono_method_set_generic_container (m, container);
11646 for (i = 0; i < count; i++) {
11647 MonoReflectionGenericParam *gp =
11648 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11649 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11650 mono_error_assert_ok (&error);
11651 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11652 container->type_params [i] = *param;
11656 * The method signature might have pointers to generic parameters that belong to other methods.
11657 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11658 * generic parameters.
11660 for (i = 0; i < m->signature->param_count; ++i) {
11661 MonoType *t = m->signature->params [i];
11662 if (t->type == MONO_TYPE_MVAR) {
11663 MonoGenericParam *gparam = t->data.generic_param;
11664 if (gparam->num < count) {
11665 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11666 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11672 if (klass->generic_container) {
11673 container->parent = klass->generic_container;
11674 container->context.class_inst = klass->generic_container->context.class_inst;
11676 container->context.method_inst = mono_get_shared_generic_inst (container);
11680 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11684 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11686 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11687 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11688 for (i = 0; i < rmb->nrefs; ++i)
11689 data [i + 1] = rmb->refs [i];
11694 /* Parameter info */
11697 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11698 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11699 for (i = 0; i <= m->signature->param_count; ++i) {
11700 MonoReflectionParamBuilder *pb;
11701 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11702 if ((i > 0) && (pb->attrs)) {
11703 /* Make a copy since it might point to a shared type structure */
11704 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11705 m->signature->params [i - 1]->attrs = pb->attrs;
11708 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11709 MonoDynamicImage *assembly;
11711 MonoTypeEnum def_type;
11715 if (!method_aux->param_defaults) {
11716 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11717 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11719 assembly = (MonoDynamicImage*)klass->image;
11720 idx = encode_constant (assembly, pb->def_value, &def_type);
11721 /* Copy the data from the blob since it might get realloc-ed */
11722 p = assembly->blob.data + idx;
11723 len = mono_metadata_decode_blob_size (p, &p2);
11725 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11726 method_aux->param_default_types [i] = def_type;
11727 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11731 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11732 g_assert (mono_error_ok (&error));
11735 if (!method_aux->param_cattr)
11736 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11737 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11743 /* Parameter marshalling */
11746 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11747 MonoReflectionParamBuilder *pb;
11748 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11749 if (pb->marshal_info) {
11751 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11752 specs [pb->position] =
11753 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11757 if (specs != NULL) {
11759 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11760 method_aux->param_marshall = specs;
11763 if (image_is_dynamic (klass->image) && method_aux)
11764 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11766 mono_loader_unlock ();
11772 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11774 ReflectionMethodBuilder rmb;
11775 MonoMethodSignature *sig;
11777 mono_loader_lock ();
11778 sig = ctor_builder_to_signature (klass->image, mb);
11779 mono_loader_unlock ();
11781 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11784 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11785 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11787 /* If we are in a generic class, we might be called multiple times from inflate_method */
11788 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11789 /* ilgen is no longer needed */
11793 return mb->mhandle;
11797 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11799 ReflectionMethodBuilder rmb;
11800 MonoMethodSignature *sig;
11802 mono_error_init (error);
11804 mono_loader_lock ();
11805 sig = method_builder_to_signature (klass->image, mb);
11806 mono_loader_unlock ();
11808 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11811 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11812 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11814 /* If we are in a generic class, we might be called multiple times from inflate_method */
11815 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11816 /* ilgen is no longer needed */
11819 return mb->mhandle;
11822 static MonoClassField*
11823 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11825 MonoClassField *field;
11829 field = g_new0 (MonoClassField, 1);
11831 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11832 g_assert (mono_error_ok (&error));
11833 if (fb->attrs || fb->modreq || fb->modopt) {
11834 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11835 if (!is_ok (&error)) {
11837 mono_error_raise_exception (&error); /* FIXME don't raise here */
11839 field->type = mono_metadata_type_dup (NULL, type);
11840 field->type->attrs = fb->attrs;
11842 g_assert (image_is_dynamic (klass->image));
11843 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11844 g_free (field->type);
11845 field->type = mono_metadata_type_dup (klass->image, custom);
11848 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11849 if (!is_ok (&error)) {
11851 mono_error_raise_exception (&error); /* FIXME don't raise here */
11854 if (fb->offset != -1)
11855 field->offset = fb->offset;
11856 field->parent = klass;
11857 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11859 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11866 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11870 MonoReflectionTypeBuilder *tb = NULL;
11871 gboolean is_dynamic = FALSE;
11872 MonoClass *geninst;
11874 mono_loader_lock ();
11876 if (is_sre_type_builder (mono_object_class (type))) {
11877 tb = (MonoReflectionTypeBuilder *) type;
11880 } else if (is_sre_generic_instance (mono_object_class (type))) {
11881 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11882 MonoReflectionType *gtd = rgi->generic_type;
11884 if (is_sre_type_builder (mono_object_class (gtd))) {
11885 tb = (MonoReflectionTypeBuilder *)gtd;
11890 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11891 if (tb && tb->generic_container)
11892 mono_reflection_create_generic_class (tb);
11894 MonoType *t = mono_reflection_type_get_handle (type, &error);
11895 mono_error_raise_exception (&error); /* FIXME don't raise here */
11897 klass = mono_class_from_mono_type (t);
11898 if (!klass->generic_container) {
11899 mono_loader_unlock ();
11903 if (klass->wastypebuilder) {
11904 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11909 mono_loader_unlock ();
11911 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11913 return &geninst->byval_arg;
11917 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11919 MonoGenericClass *gclass;
11920 MonoGenericInst *inst;
11922 g_assert (klass->generic_container);
11924 inst = mono_metadata_get_generic_inst (type_argc, types);
11925 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11927 return mono_generic_class_get_class (gclass);
11930 MonoReflectionMethod*
11931 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11935 MonoMethod *method, *inflated;
11936 MonoMethodInflated *imethod;
11937 MonoGenericContext tmp_context;
11938 MonoGenericInst *ginst;
11939 MonoType **type_argv;
11942 /*FIXME but this no longer should happen*/
11943 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11944 #ifndef DISABLE_REFLECTION_EMIT
11945 MonoReflectionMethodBuilder *mb = NULL;
11949 mb = (MonoReflectionMethodBuilder *) rmethod;
11950 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11951 mono_error_raise_exception (&error); /* FIXME don't raise here */
11952 klass = mono_class_from_mono_type (tb);
11954 method = methodbuilder_to_mono_method (klass, mb, &error);
11956 mono_error_raise_exception (&error); /* FIXME don't raise here */
11958 g_assert_not_reached ();
11962 method = rmethod->method;
11965 klass = method->klass;
11967 if (method->is_inflated)
11968 method = ((MonoMethodInflated *) method)->declaring;
11970 count = mono_method_signature (method)->generic_param_count;
11971 if (count != mono_array_length (types))
11974 type_argv = g_new0 (MonoType *, count);
11975 for (i = 0; i < count; i++) {
11976 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11977 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11978 if (!is_ok (&error)) {
11979 g_free (type_argv);
11980 mono_error_raise_exception (&error); /* FIXME don't raise here */
11983 ginst = mono_metadata_get_generic_inst (count, type_argv);
11984 g_free (type_argv);
11986 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11987 tmp_context.method_inst = ginst;
11989 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11990 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11991 imethod = (MonoMethodInflated *) inflated;
11993 /*FIXME but I think this is no longer necessary*/
11994 if (image_is_dynamic (method->klass->image)) {
11995 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11997 * This table maps metadata structures representing inflated methods/fields
11998 * to the reflection objects representing their generic definitions.
12000 mono_image_lock ((MonoImage*)image);
12001 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12002 mono_image_unlock ((MonoImage*)image);
12005 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12006 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12008 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12009 mono_error_raise_exception (&error); /* FIXME don't raise here */
12013 #ifndef DISABLE_REFLECTION_EMIT
12015 static MonoMethod *
12016 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12018 MonoMethodInflated *imethod;
12019 MonoGenericContext *context;
12023 * With generic code sharing the klass might not be inflated.
12024 * This can happen because classes inflated with their own
12025 * type arguments are "normalized" to the uninflated class.
12027 if (!klass->generic_class)
12030 context = mono_class_get_context (klass);
12032 if (klass->method.count && klass->methods) {
12033 /* Find the already created inflated method */
12034 for (i = 0; i < klass->method.count; ++i) {
12035 g_assert (klass->methods [i]->is_inflated);
12036 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12039 g_assert (i < klass->method.count);
12040 imethod = (MonoMethodInflated*)klass->methods [i];
12043 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12044 mono_error_assert_ok (&error);
12047 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12048 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12050 mono_image_lock ((MonoImage*)image);
12051 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12052 mono_image_unlock ((MonoImage*)image);
12054 return (MonoMethod *) imethod;
12057 static MonoMethod *
12058 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12060 MonoMethod *method;
12063 mono_error_init (error);
12065 MonoClass *type_class = mono_object_class (type);
12067 if (is_sre_generic_instance (type_class)) {
12068 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12069 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12070 return_val_if_nok (error, NULL);
12071 gklass = mono_class_from_mono_type (generic_type);
12072 } else if (is_sre_type_builder (type_class)) {
12073 MonoType *t = mono_reflection_type_get_handle (type, error);
12074 return_val_if_nok (error, NULL);
12075 gklass = mono_class_from_mono_type (t);
12076 } else if (type->type) {
12077 gklass = mono_class_from_mono_type (type->type);
12078 gklass = mono_class_get_generic_type_definition (gklass);
12080 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12083 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12084 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12085 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12087 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12091 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12092 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12095 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12096 method = ((MonoReflectionMethod *) obj)->method;
12098 method = NULL; /* prevent compiler warning */
12099 g_error ("can't handle type %s", obj->vtable->klass->name);
12102 MonoType *t = mono_reflection_type_get_handle (type, error);
12103 return_val_if_nok (error, NULL);
12104 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12107 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12109 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12112 MonoGenericClass *gclass;
12113 MonoDynamicGenericClass *dgclass;
12114 MonoClass *klass, *gklass;
12118 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12119 mono_error_raise_exception (&error); /* FIXME don't raise here */
12120 klass = mono_class_from_mono_type (gtype);
12121 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12122 gclass = gtype->data.generic_class;
12124 if (!gclass->is_dynamic)
12127 dgclass = (MonoDynamicGenericClass *) gclass;
12129 if (dgclass->initialized)
12132 gklass = gclass->container_class;
12133 mono_class_init (gklass);
12135 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12137 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12138 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12139 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12141 for (i = 0; i < dgclass->count_fields; i++) {
12143 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12144 MonoClassField *field, *inflated_field = NULL;
12146 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12147 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12148 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12149 field = ((MonoReflectionField *) obj)->field;
12151 field = NULL; /* prevent compiler warning */
12152 g_assert_not_reached ();
12155 dgclass->fields [i] = *field;
12156 dgclass->fields [i].parent = klass;
12157 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12158 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12159 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12160 dgclass->field_generic_types [i] = field->type;
12161 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12162 dgclass->field_objects [i] = obj;
12164 if (inflated_field) {
12165 g_free (inflated_field);
12167 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12171 dgclass->initialized = TRUE;
12175 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12177 MonoDynamicGenericClass *dgclass;
12180 g_assert (gclass->is_dynamic);
12182 dgclass = (MonoDynamicGenericClass *)gclass;
12184 for (i = 0; i < dgclass->count_fields; ++i) {
12185 MonoClassField *field = dgclass->fields + i;
12186 mono_metadata_free_type (field->type);
12187 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12192 fix_partial_generic_class (MonoClass *klass)
12194 MonoClass *gklass = klass->generic_class->container_class;
12195 MonoDynamicGenericClass *dgclass;
12198 if (klass->wastypebuilder)
12201 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12202 if (klass->parent != gklass->parent) {
12204 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12205 if (mono_error_ok (&error)) {
12206 MonoClass *parent = mono_class_from_mono_type (parent_type);
12207 mono_metadata_free_type (parent_type);
12208 if (parent != klass->parent) {
12209 /*fool mono_class_setup_parent*/
12210 klass->supertypes = NULL;
12211 mono_class_setup_parent (klass, parent);
12214 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12215 mono_error_cleanup (&error);
12216 if (gklass->wastypebuilder)
12217 klass->wastypebuilder = TRUE;
12222 if (!dgclass->initialized)
12225 if (klass->method.count != gklass->method.count) {
12226 klass->method.count = gklass->method.count;
12227 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12229 for (i = 0; i < klass->method.count; i++) {
12231 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12232 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12233 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12237 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12238 klass->interface_count = gklass->interface_count;
12239 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12240 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12242 for (i = 0; i < gklass->interface_count; ++i) {
12244 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12245 mono_error_raise_exception (&error); /* FIXME don't raise here */
12247 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12248 mono_metadata_free_type (iface_type);
12250 ensure_runtime_vtable (klass->interfaces [i], &error);
12251 mono_error_raise_exception (&error); /* FIXME don't raise here */
12253 klass->interfaces_inited = 1;
12256 if (klass->field.count != gklass->field.count) {
12257 klass->field.count = gklass->field.count;
12258 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12260 for (i = 0; i < klass->field.count; i++) {
12262 klass->fields [i] = gklass->fields [i];
12263 klass->fields [i].parent = klass;
12264 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12265 mono_error_raise_exception (&error); /* FIXME don't raise here */
12269 /*We can only finish with this klass once it's parent has as well*/
12270 if (gklass->wastypebuilder)
12271 klass->wastypebuilder = TRUE;
12276 * ensure_generic_class_runtime_vtable:
12277 * @klass a generic class
12278 * @error set on error
12280 * Ensures that the generic container of @klass has a vtable and
12281 * returns TRUE on success. On error returns FALSE and sets @error.
12284 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12286 MonoClass *gklass = klass->generic_class->container_class;
12288 mono_error_init (error);
12290 if (!ensure_runtime_vtable (gklass, error))
12293 fix_partial_generic_class (klass);
12299 * ensure_runtime_vtable:
12301 * @error set on error
12303 * Ensures that @klass has a vtable and returns TRUE on success. On
12304 * error returns FALSE and sets @error.
12307 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12309 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12312 mono_error_init (error);
12314 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12317 if (!ensure_runtime_vtable (klass->parent, error))
12321 num = tb->ctors? mono_array_length (tb->ctors): 0;
12322 num += tb->num_methods;
12323 klass->method.count = num;
12324 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12325 num = tb->ctors? mono_array_length (tb->ctors): 0;
12326 for (i = 0; i < num; ++i) {
12327 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12330 klass->methods [i] = ctor;
12332 num = tb->num_methods;
12334 for (i = 0; i < num; ++i) {
12335 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12338 klass->methods [j++] = meth;
12341 if (tb->interfaces) {
12342 klass->interface_count = mono_array_length (tb->interfaces);
12343 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12344 for (i = 0; i < klass->interface_count; ++i) {
12345 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12346 return_val_if_nok (error, FALSE);
12347 klass->interfaces [i] = mono_class_from_mono_type (iface);
12348 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12351 klass->interfaces_inited = 1;
12353 } else if (klass->generic_class){
12354 if (!ensure_generic_class_runtime_vtable (klass, error))
12358 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12360 for (i = 0; i < klass->method.count; ++i) {
12361 MonoMethod *im = klass->methods [i];
12362 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12363 im->slot = slot_num++;
12366 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12367 mono_class_setup_interface_offsets (klass);
12368 mono_class_setup_interface_id (klass);
12372 * The generic vtable is needed even if image->run is not set since some
12373 * runtime code like ves_icall_Type_GetMethodsByName depends on
12374 * method->slot being defined.
12378 * tb->methods could not be freed since it is used for determining
12379 * overrides during dynamic vtable construction.
12386 mono_reflection_method_get_handle (MonoObject *method)
12389 MonoClass *klass = mono_object_class (method);
12390 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12391 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12392 return sr_method->method;
12394 if (is_sre_method_builder (klass)) {
12395 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12396 return mb->mhandle;
12398 if (is_sre_method_on_tb_inst (klass)) {
12399 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12400 MonoMethod *result;
12401 /*FIXME move this to a proper method and unify with resolve_object*/
12402 if (m->method_args) {
12403 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12404 mono_error_raise_exception (&error); /* FIXME don't raise here */
12406 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12407 mono_error_raise_exception (&error); /* FIXME don't raise here */
12408 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12409 MonoMethod *mono_method;
12411 if (is_sre_method_builder (mono_object_class (m->mb)))
12412 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12413 else if (is_sr_mono_method (mono_object_class (m->mb)))
12414 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12416 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)));
12418 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12423 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12428 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12430 MonoReflectionTypeBuilder *tb;
12432 MonoReflectionMethod *m;
12435 *num_overrides = 0;
12437 g_assert (image_is_dynamic (klass->image));
12439 if (!mono_class_get_ref_info (klass))
12442 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12444 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12448 for (i = 0; i < tb->num_methods; ++i) {
12449 MonoReflectionMethodBuilder *mb =
12450 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12451 if (mb->override_methods)
12452 onum += mono_array_length (mb->override_methods);
12457 *overrides = g_new0 (MonoMethod*, onum * 2);
12460 for (i = 0; i < tb->num_methods; ++i) {
12461 MonoReflectionMethodBuilder *mb =
12462 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12463 if (mb->override_methods) {
12464 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12465 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12467 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12468 (*overrides) [onum * 2 + 1] = mb->mhandle;
12470 g_assert (mb->mhandle);
12478 *num_overrides = onum;
12482 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12484 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12485 MonoReflectionFieldBuilder *fb;
12486 MonoClassField *field;
12487 MonoImage *image = klass->image;
12488 const char *p, *p2;
12490 guint32 len, idx, real_size = 0;
12492 klass->field.count = tb->num_fields;
12493 klass->field.first = 0;
12495 mono_error_init (error);
12497 if (tb->class_size) {
12498 if ((tb->packing_size & 0xffffff00) != 0) {
12499 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12500 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12503 klass->packing_size = tb->packing_size;
12504 real_size = klass->instance_size + tb->class_size;
12507 if (!klass->field.count) {
12508 klass->instance_size = MAX (klass->instance_size, real_size);
12512 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12513 mono_class_alloc_ext (klass);
12514 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12516 This is, guess what, a hack.
12517 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12518 On the static path no field class is resolved, only types are built. This is the right thing to do
12520 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12522 klass->size_inited = 1;
12524 for (i = 0; i < klass->field.count; ++i) {
12525 MonoArray *rva_data;
12526 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12527 field = &klass->fields [i];
12528 field->name = mono_string_to_utf8_image (image, fb->name, error);
12529 if (!mono_error_ok (error))
12532 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12533 return_if_nok (error);
12534 field->type = mono_metadata_type_dup (klass->image, type);
12535 field->type->attrs = fb->attrs;
12537 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12538 return_if_nok (error);
12541 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12542 char *base = mono_array_addr (rva_data, char, 0);
12543 size_t size = mono_array_length (rva_data);
12544 char *data = (char *)mono_image_alloc (klass->image, size);
12545 memcpy (data, base, size);
12546 klass->ext->field_def_values [i].data = data;
12548 if (fb->offset != -1)
12549 field->offset = fb->offset;
12550 field->parent = klass;
12551 fb->handle = field;
12552 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12554 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12555 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12557 if (fb->def_value) {
12558 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12559 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12560 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12561 /* Copy the data from the blob since it might get realloc-ed */
12562 p = assembly->blob.data + idx;
12563 len = mono_metadata_decode_blob_size (p, &p2);
12565 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12566 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12570 klass->instance_size = MAX (klass->instance_size, real_size);
12571 mono_class_layout_fields (klass);
12575 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12577 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12578 MonoReflectionPropertyBuilder *pb;
12579 MonoImage *image = klass->image;
12580 MonoProperty *properties;
12583 mono_error_init (error);
12586 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12588 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12589 klass->ext->property.first = 0;
12591 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12592 klass->ext->properties = properties;
12593 for (i = 0; i < klass->ext->property.count; ++i) {
12594 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12595 properties [i].parent = klass;
12596 properties [i].attrs = pb->attrs;
12597 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12598 if (!mono_error_ok (error))
12600 if (pb->get_method)
12601 properties [i].get = pb->get_method->mhandle;
12602 if (pb->set_method)
12603 properties [i].set = pb->set_method->mhandle;
12605 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12606 if (pb->def_value) {
12608 const char *p, *p2;
12609 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12610 if (!klass->ext->prop_def_values)
12611 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12612 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12613 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12614 /* Copy the data from the blob since it might get realloc-ed */
12615 p = assembly->blob.data + idx;
12616 len = mono_metadata_decode_blob_size (p, &p2);
12618 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12619 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12624 MonoReflectionEvent *
12625 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12628 MonoEvent *event = g_new0 (MonoEvent, 1);
12631 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12632 mono_error_raise_exception (&error); /* FIXME don't raise here */
12633 klass = mono_class_from_mono_type (type);
12635 event->parent = klass;
12636 event->attrs = eb->attrs;
12637 event->name = mono_string_to_utf8 (eb->name);
12638 if (eb->add_method)
12639 event->add = eb->add_method->mhandle;
12640 if (eb->remove_method)
12641 event->remove = eb->remove_method->mhandle;
12642 if (eb->raise_method)
12643 event->raise = eb->raise_method->mhandle;
12645 #ifndef MONO_SMALL_CONFIG
12646 if (eb->other_methods) {
12648 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12649 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12650 MonoReflectionMethodBuilder *mb =
12651 mono_array_get (eb->other_methods,
12652 MonoReflectionMethodBuilder*, j);
12653 event->other [j] = mb->mhandle;
12658 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12659 mono_error_raise_exception (&error); /* FIXME don't raise here */
12664 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12666 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12667 MonoReflectionEventBuilder *eb;
12668 MonoImage *image = klass->image;
12672 mono_error_init (error);
12675 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12677 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12678 klass->ext->event.first = 0;
12680 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12681 klass->ext->events = events;
12682 for (i = 0; i < klass->ext->event.count; ++i) {
12683 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12684 events [i].parent = klass;
12685 events [i].attrs = eb->attrs;
12686 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12687 if (!mono_error_ok (error))
12689 if (eb->add_method)
12690 events [i].add = eb->add_method->mhandle;
12691 if (eb->remove_method)
12692 events [i].remove = eb->remove_method->mhandle;
12693 if (eb->raise_method)
12694 events [i].raise = eb->raise_method->mhandle;
12696 #ifndef MONO_SMALL_CONFIG
12697 if (eb->other_methods) {
12699 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12700 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12701 MonoReflectionMethodBuilder *mb =
12702 mono_array_get (eb->other_methods,
12703 MonoReflectionMethodBuilder*, j);
12704 events [i].other [j] = mb->mhandle;
12708 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12713 remove_instantiations_of_and_ensure_contents (gpointer key,
12715 gpointer user_data)
12717 MonoType *type = (MonoType*)key;
12718 MonoClass *klass = (MonoClass*)user_data;
12720 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12721 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12728 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12730 mono_error_init (error);
12736 for (i = 0; i < mono_array_length (arr); ++i) {
12737 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12738 if (!mono_error_ok (error))
12743 MonoReflectionType*
12744 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12748 MonoDomain* domain;
12749 MonoReflectionType* res;
12752 domain = mono_object_domain (tb);
12753 klass = mono_class_from_mono_type (tb->type.type);
12756 * Check for user defined Type subclasses.
12758 RESOLVE_TYPE (tb->parent, &error);
12759 mono_error_raise_exception (&error); /* FIXME don't raise here */
12760 check_array_for_usertypes (tb->interfaces, &error);
12761 mono_error_raise_exception (&error); /*FIXME don't raise here */
12763 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12764 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12766 RESOLVE_TYPE (fb->type, &error);
12767 mono_error_raise_exception (&error); /* FIXME don't raise here */
12768 check_array_for_usertypes (fb->modreq, &error);
12769 mono_error_raise_exception (&error); /*FIXME don't raise here */
12770 check_array_for_usertypes (fb->modopt, &error);
12771 mono_error_raise_exception (&error); /*FIXME don't raise here */
12772 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12773 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12774 mono_error_raise_exception (&error); /* FIXME don't raise here */
12780 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12781 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12783 RESOLVE_TYPE (mb->rtype, &error);
12784 mono_error_raise_exception (&error); /* FIXME don't raise here */
12785 check_array_for_usertypes (mb->return_modreq, &error);
12786 mono_error_raise_exception (&error); /*FIXME don't raise here */
12787 check_array_for_usertypes (mb->return_modopt, &error);
12788 mono_error_raise_exception (&error); /*FIXME don't raise here */
12789 check_array_for_usertypes (mb->parameters, &error);
12790 mono_error_raise_exception (&error); /*FIXME don't raise here */
12791 if (mb->param_modreq)
12792 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12793 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12794 mono_error_raise_exception (&error); /*FIXME don't raise here */
12796 if (mb->param_modopt)
12797 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12798 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12799 mono_error_raise_exception (&error); /*FIXME don't raise here */
12805 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12806 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12808 check_array_for_usertypes (mb->parameters, &error);
12809 mono_error_raise_exception (&error); /*FIXME don't raise here */
12810 if (mb->param_modreq)
12811 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12812 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12813 mono_error_raise_exception (&error); /*FIXME don't raise here */
12815 if (mb->param_modopt)
12816 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12817 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12818 mono_error_raise_exception (&error); /*FIXME don't raise here */
12824 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12827 * we need to lock the domain because the lock will be taken inside
12828 * So, we need to keep the locking order correct.
12830 mono_loader_lock ();
12831 mono_domain_lock (domain);
12832 if (klass->wastypebuilder) {
12833 mono_domain_unlock (domain);
12834 mono_loader_unlock ();
12836 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12837 mono_error_raise_exception (&error); /* FIXME don't raise here */
12842 * Fields to set in klass:
12843 * the various flags: delegate/unicode/contextbound etc.
12845 klass->flags = tb->attrs;
12846 klass->has_cctor = 1;
12847 klass->has_finalize = 1;
12848 klass->has_finalize_inited = 1;
12850 mono_class_setup_parent (klass, klass->parent);
12851 /* fool mono_class_setup_supertypes */
12852 klass->supertypes = NULL;
12853 mono_class_setup_supertypes (klass);
12854 mono_class_setup_mono_type (klass);
12857 if (!((MonoDynamicImage*)klass->image)->run) {
12858 if (klass->generic_container) {
12859 /* FIXME: The code below can't handle generic classes */
12860 klass->wastypebuilder = TRUE;
12861 mono_loader_unlock ();
12862 mono_domain_unlock (domain);
12864 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12865 mono_error_raise_exception (&error); /* FIXME don't raise here */
12872 /* enums are done right away */
12873 if (!klass->enumtype)
12874 if (!ensure_runtime_vtable (klass, &error))
12877 if (tb->subtypes) {
12878 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12879 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12880 mono_class_alloc_ext (klass);
12881 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12882 if (!is_ok (&error)) goto failure;
12883 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12887 klass->nested_classes_inited = TRUE;
12889 /* fields and object layout */
12890 if (klass->parent) {
12891 if (!klass->parent->size_inited)
12892 mono_class_init (klass->parent);
12893 klass->instance_size = klass->parent->instance_size;
12894 klass->sizes.class_size = 0;
12895 klass->min_align = klass->parent->min_align;
12896 /* if the type has no fields we won't call the field_setup
12897 * routine which sets up klass->has_references.
12899 klass->has_references |= klass->parent->has_references;
12901 klass->instance_size = sizeof (MonoObject);
12902 klass->min_align = 1;
12905 /* FIXME: handle packing_size and instance_size */
12906 typebuilder_setup_fields (klass, &error);
12907 if (!mono_error_ok (&error))
12909 typebuilder_setup_properties (klass, &error);
12910 if (!mono_error_ok (&error))
12913 typebuilder_setup_events (klass, &error);
12914 if (!mono_error_ok (&error))
12917 klass->wastypebuilder = TRUE;
12920 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12921 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12922 * we want to return normal System.MonoType objects, so clear these out from the cache.
12924 * Together with this we must ensure the contents of all instances to match the created type.
12926 if (domain->type_hash && klass->generic_container)
12927 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12929 mono_domain_unlock (domain);
12930 mono_loader_unlock ();
12932 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12933 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12934 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12937 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12938 mono_error_raise_exception (&error); /* FIXME don't raise here */
12940 g_assert (res != (MonoReflectionType*)tb);
12945 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12946 klass->wastypebuilder = TRUE;
12947 mono_domain_unlock (domain);
12948 mono_loader_unlock ();
12949 mono_error_raise_exception (&error);
12954 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12956 MonoGenericParamFull *param;
12961 image = &gparam->tbuilder->module->dynamic_image->image;
12963 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12965 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12966 g_assert (mono_error_ok (&error));
12967 param->param.num = gparam->index;
12969 if (gparam->mbuilder) {
12970 if (!gparam->mbuilder->generic_container) {
12971 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12972 mono_error_raise_exception (&error); /* FIXME don't raise here */
12974 MonoClass *klass = mono_class_from_mono_type (tb);
12975 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12976 gparam->mbuilder->generic_container->is_method = TRUE;
12978 * Cannot set owner.method, since the MonoMethod is not created yet.
12979 * Set the image field instead, so type_in_image () works.
12981 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12982 gparam->mbuilder->generic_container->owner.image = klass->image;
12984 param->param.owner = gparam->mbuilder->generic_container;
12985 } else if (gparam->tbuilder) {
12986 if (!gparam->tbuilder->generic_container) {
12987 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12988 mono_error_raise_exception (&error); /* FIXME don't raise here */
12989 MonoClass *klass = mono_class_from_mono_type (tb);
12990 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12991 gparam->tbuilder->generic_container->owner.klass = klass;
12993 param->param.owner = gparam->tbuilder->generic_container;
12996 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12998 gparam->type.type = &pklass->byval_arg;
13000 mono_class_set_ref_info (pklass, gparam);
13001 mono_image_append_class_to_reflection_info_set (pklass);
13005 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13008 MonoReflectionModuleBuilder *module = sig->module;
13009 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13010 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13015 check_array_for_usertypes (sig->arguments, &error);
13016 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13018 sigbuffer_init (&buf, 32);
13020 sigbuffer_add_value (&buf, 0x07);
13021 sigbuffer_add_value (&buf, na);
13022 if (assembly != NULL){
13023 for (i = 0; i < na; ++i) {
13024 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13025 encode_reflection_type (assembly, type, &buf, &error);
13026 if (!is_ok (&error)) goto fail;
13030 buflen = buf.p - buf.buf;
13031 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13032 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13033 sigbuffer_free (&buf);
13036 sigbuffer_free (&buf);
13037 mono_error_raise_exception (&error); /* FIXME don't raise here */
13042 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13045 MonoDynamicImage *assembly = sig->module->dynamic_image;
13046 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13051 check_array_for_usertypes (sig->arguments, &error);
13052 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13054 sigbuffer_init (&buf, 32);
13056 sigbuffer_add_value (&buf, 0x06);
13057 for (i = 0; i < na; ++i) {
13058 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13059 encode_reflection_type (assembly, type, &buf, &error);
13060 if (!is_ok (&error))
13064 buflen = buf.p - buf.buf;
13065 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13066 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13067 sigbuffer_free (&buf);
13071 sigbuffer_free (&buf);
13072 mono_error_raise_exception (&error); /* FIXME don't raise here */
13077 MonoMethod *handle;
13078 MonoDomain *domain;
13079 } DynamicMethodReleaseData;
13082 * The runtime automatically clean up those after finalization.
13084 static MonoReferenceQueue *dynamic_method_queue;
13087 free_dynamic_method (void *dynamic_method)
13089 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13090 MonoDomain *domain = data->domain;
13091 MonoMethod *method = data->handle;
13094 mono_domain_lock (domain);
13095 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13096 g_hash_table_remove (domain->method_to_dyn_method, method);
13097 mono_domain_unlock (domain);
13098 g_assert (dis_link);
13099 mono_gchandle_free (dis_link);
13101 mono_runtime_free_method (domain, method);
13106 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13109 MonoReferenceQueue *queue;
13110 MonoMethod *handle;
13111 DynamicMethodReleaseData *release_data;
13112 ReflectionMethodBuilder rmb;
13113 MonoMethodSignature *sig;
13115 MonoDomain *domain;
13119 if (mono_runtime_is_shutting_down ())
13120 mono_raise_exception (mono_get_exception_invalid_operation (""));
13122 if (!(queue = dynamic_method_queue)) {
13123 mono_loader_lock ();
13124 if (!(queue = dynamic_method_queue))
13125 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13126 mono_loader_unlock ();
13129 sig = dynamic_method_to_signature (mb);
13131 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13134 * Resolve references.
13137 * Every second entry in the refs array is reserved for storing handle_class,
13138 * which is needed by the ldtoken implementation in the JIT.
13140 rmb.nrefs = mb->nrefs;
13141 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13142 for (i = 0; i < mb->nrefs; i += 2) {
13143 MonoClass *handle_class;
13145 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13147 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13148 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13150 * The referenced DynamicMethod should already be created by the managed
13151 * code, except in the case of circular references. In that case, we store
13152 * method in the refs array, and fix it up later when the referenced
13153 * DynamicMethod is created.
13155 if (method->mhandle) {
13156 ref = method->mhandle;
13158 /* FIXME: GC object stored in unmanaged memory */
13161 /* FIXME: GC object stored in unmanaged memory */
13162 method->referenced_by = g_slist_append (method->referenced_by, mb);
13164 handle_class = mono_defaults.methodhandle_class;
13166 MonoException *ex = NULL;
13167 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13169 ex = mono_get_exception_type_load (NULL, NULL);
13170 else if (mono_security_core_clr_enabled ())
13171 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13175 mono_raise_exception (ex);
13180 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13181 rmb.refs [i + 1] = handle_class;
13185 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13186 if (!is_ok (&error)) {
13188 mono_error_raise_exception (&error); /* FIXME don't raise here */
13190 klass = mono_class_from_mono_type (owner_type);
13192 klass = mono_defaults.object_class;
13195 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13196 release_data = g_new (DynamicMethodReleaseData, 1);
13197 release_data->handle = handle;
13198 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13199 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13200 g_free (release_data);
13202 /* Fix up refs entries pointing at us */
13203 for (l = mb->referenced_by; l; l = l->next) {
13204 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13205 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13208 g_assert (method->mhandle);
13210 data = (gpointer*)wrapper->method_data;
13211 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13212 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13213 data [i + 1] = mb->mhandle;
13216 g_slist_free (mb->referenced_by);
13220 /* ilgen is no longer needed */
13223 domain = mono_domain_get ();
13224 mono_domain_lock (domain);
13225 if (!domain->method_to_dyn_method)
13226 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13227 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13228 mono_domain_unlock (domain);
13231 #endif /* DISABLE_REFLECTION_EMIT */
13235 * mono_reflection_is_valid_dynamic_token:
13237 * Returns TRUE if token is valid.
13241 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13243 return lookup_dyn_token (image, token) != NULL;
13246 MonoMethodSignature *
13247 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13249 MonoMethodSignature *sig;
13250 g_assert (image_is_dynamic (image));
13252 mono_error_init (error);
13254 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13258 return mono_method_signature_checked (method, error);
13261 #ifndef DISABLE_REFLECTION_EMIT
13264 * mono_reflection_lookup_dynamic_token:
13266 * Finish the Builder object pointed to by TOKEN and return the corresponding
13267 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13268 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13271 * LOCKING: Take the loader lock
13274 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13276 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13280 obj = lookup_dyn_token (assembly, token);
13283 g_error ("Could not find required dynamic token 0x%08x", token);
13289 handle_class = &klass;
13290 return resolve_object (image, obj, handle_class, context);
13294 * ensure_complete_type:
13296 * Ensure that KLASS is completed if it is a dynamic type, or references
13300 ensure_complete_type (MonoClass *klass)
13304 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13305 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13307 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13308 mono_error_raise_exception (&error); /* FIXME don't raise here */
13310 // Asserting here could break a lot of code
13311 //g_assert (klass->wastypebuilder);
13314 if (klass->generic_class) {
13315 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13318 for (i = 0; i < inst->type_argc; ++i) {
13319 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13325 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13328 gpointer result = NULL;
13330 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13331 result = mono_string_intern_checked ((MonoString*)obj, &error);
13332 mono_error_raise_exception (&error); /* FIXME don't raise here */
13333 *handle_class = mono_defaults.string_class;
13335 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13336 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13337 mono_error_raise_exception (&error); /* FIXME don't raise here */
13338 MonoClass *mc = mono_class_from_mono_type (type);
13339 if (!mono_class_init (mc))
13340 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13343 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13344 mono_error_raise_exception (&error); /* FIXME don't raise here */
13346 result = mono_class_from_mono_type (inflated);
13347 mono_metadata_free_type (inflated);
13349 result = mono_class_from_mono_type (type);
13351 *handle_class = mono_defaults.typehandle_class;
13353 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13354 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13355 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13356 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13357 result = ((MonoReflectionMethod*)obj)->method;
13360 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13361 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13363 *handle_class = mono_defaults.methodhandle_class;
13365 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13366 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13367 result = mb->mhandle;
13369 /* Type is not yet created */
13370 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13372 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13373 mono_error_raise_exception (&error); /* FIXME don't raise here */
13376 * Hopefully this has been filled in by calling CreateType() on the
13380 * TODO: This won't work if the application finishes another
13381 * TypeBuilder instance instead of this one.
13383 result = mb->mhandle;
13387 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13388 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13390 *handle_class = mono_defaults.methodhandle_class;
13391 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13392 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13394 result = cb->mhandle;
13396 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13398 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13399 mono_error_raise_exception (&error); /* FIXME don't raise here */
13400 result = cb->mhandle;
13404 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13405 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13407 *handle_class = mono_defaults.methodhandle_class;
13408 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13409 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13411 ensure_complete_type (field->parent);
13413 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13414 mono_error_raise_exception (&error); /* FIXME don't raise here */
13416 MonoClass *klass = mono_class_from_mono_type (inflated);
13417 MonoClassField *inflated_field;
13418 gpointer iter = NULL;
13419 mono_metadata_free_type (inflated);
13420 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13421 if (!strcmp (field->name, inflated_field->name))
13424 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13425 result = inflated_field;
13429 *handle_class = mono_defaults.fieldhandle_class;
13431 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13432 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13433 result = fb->handle;
13436 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13438 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13439 mono_error_raise_exception (&error); /* FIXME don't raise here */
13440 result = fb->handle;
13443 if (fb->handle && fb->handle->parent->generic_container) {
13444 MonoClass *klass = fb->handle->parent;
13445 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13446 mono_error_raise_exception (&error); /* FIXME don't raise here */
13448 MonoClass *inflated = mono_class_from_mono_type (type);
13450 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13452 mono_metadata_free_type (type);
13454 *handle_class = mono_defaults.fieldhandle_class;
13455 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13456 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13457 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13458 mono_error_raise_exception (&error); /* FIXME don't raise here */
13461 klass = type->data.klass;
13462 if (klass->wastypebuilder) {
13463 /* Already created */
13467 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13468 mono_error_raise_exception (&error); /* FIXME don't raise here */
13469 result = type->data.klass;
13472 *handle_class = mono_defaults.typehandle_class;
13473 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13474 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13475 MonoMethodSignature *sig;
13478 if (helper->arguments)
13479 nargs = mono_array_length (helper->arguments);
13483 sig = mono_metadata_signature_alloc (image, nargs);
13484 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13485 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13487 if (helper->unmanaged_call_conv) { /* unmanaged */
13488 sig->call_convention = helper->unmanaged_call_conv - 1;
13489 sig->pinvoke = TRUE;
13490 } else if (helper->call_conv & 0x02) {
13491 sig->call_convention = MONO_CALL_VARARG;
13493 sig->call_convention = MONO_CALL_DEFAULT;
13496 sig->param_count = nargs;
13497 /* TODO: Copy type ? */
13498 sig->ret = helper->return_type->type;
13499 for (i = 0; i < nargs; ++i) {
13500 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13501 mono_error_raise_exception (&error); /* FIXME don't raise here */
13505 *handle_class = NULL;
13506 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13507 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13508 /* Already created by the managed code */
13509 g_assert (method->mhandle);
13510 result = method->mhandle;
13511 *handle_class = mono_defaults.methodhandle_class;
13512 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13513 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13514 mono_error_raise_exception (&error); /* FIXME don't raise here */
13515 type = mono_class_inflate_generic_type_checked (type, context, &error);
13516 mono_error_raise_exception (&error); /* FIXME don't raise here */
13518 result = mono_class_from_mono_type (type);
13519 *handle_class = mono_defaults.typehandle_class;
13521 mono_metadata_free_type (type);
13522 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13523 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13524 mono_error_raise_exception (&error); /* FIXME don't raise here */
13525 type = mono_class_inflate_generic_type_checked (type, context, &error);
13526 mono_error_raise_exception (&error); /* FIXME don't raise here */
13528 result = mono_class_from_mono_type (type);
13529 *handle_class = mono_defaults.typehandle_class;
13531 mono_metadata_free_type (type);
13532 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13533 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13534 MonoClass *inflated;
13536 MonoClassField *field;
13538 if (is_sre_field_builder (mono_object_class (f->fb)))
13539 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13540 else if (is_sr_mono_field (mono_object_class (f->fb)))
13541 field = ((MonoReflectionField*)f->fb)->field;
13543 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)));
13545 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13546 mono_error_raise_exception (&error); /* FIXME don't raise here */
13547 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13548 mono_error_raise_exception (&error); /* FIXME don't raise here */
13550 inflated = mono_class_from_mono_type (type);
13552 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13553 ensure_complete_type (field->parent);
13555 mono_metadata_free_type (type);
13556 *handle_class = mono_defaults.fieldhandle_class;
13557 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13558 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13559 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13560 mono_error_raise_exception (&error); /* FIXME don't raise here */
13561 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13562 mono_error_raise_exception (&error); /* FIXME don't raise here */
13564 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13565 MonoMethod *method;
13567 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13568 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13569 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13570 method = ((MonoReflectionMethod *)c->cb)->method;
13572 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)));
13574 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13575 *handle_class = mono_defaults.methodhandle_class;
13576 mono_metadata_free_type (type);
13577 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13578 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13579 if (m->method_args) {
13580 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13581 mono_error_raise_exception (&error); /* FIXME don't raise here */
13583 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13584 mono_error_assert_ok (&error);
13587 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13588 mono_error_raise_exception (&error); /* FIXME don't raise here */
13589 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13590 mono_error_raise_exception (&error); /* FIXME don't raise here */
13592 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13593 MonoMethod *method;
13595 if (is_sre_method_builder (mono_object_class (m->mb)))
13596 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13597 else if (is_sr_mono_method (mono_object_class (m->mb)))
13598 method = ((MonoReflectionMethod *)m->mb)->method;
13600 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)));
13602 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13603 mono_metadata_free_type (type);
13605 *handle_class = mono_defaults.methodhandle_class;
13606 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13607 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13610 MonoMethod *method;
13614 mtype = mono_reflection_type_get_handle (m->parent, &error);
13615 mono_error_raise_exception (&error); /* FIXME don't raise here */
13616 klass = mono_class_from_mono_type (mtype);
13618 /* Find the method */
13620 name = mono_string_to_utf8 (m->name);
13622 while ((method = mono_class_get_methods (klass, &iter))) {
13623 if (!strcmp (method->name, name))
13630 // FIXME: Check parameters/return value etc. match
13633 *handle_class = mono_defaults.methodhandle_class;
13634 } else if (is_sre_array (mono_object_get_class(obj)) ||
13635 is_sre_byref (mono_object_get_class(obj)) ||
13636 is_sre_pointer (mono_object_get_class(obj))) {
13637 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13638 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13639 mono_error_raise_exception (&error); /* FIXME don't raise here */
13642 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13643 mono_error_raise_exception (&error); /* FIXME don't raise here */
13645 result = mono_class_from_mono_type (inflated);
13646 mono_metadata_free_type (inflated);
13648 result = mono_class_from_mono_type (type);
13650 *handle_class = mono_defaults.typehandle_class;
13652 g_print ("%s\n", obj->vtable->klass->name);
13653 g_assert_not_reached ();
13658 #else /* DISABLE_REFLECTION_EMIT */
13661 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13663 g_assert_not_reached ();
13668 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13670 g_assert_not_reached ();
13674 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13676 g_assert_not_reached ();
13680 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13682 g_assert_not_reached ();
13686 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13688 g_assert_not_reached ();
13692 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13694 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13698 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13700 g_assert_not_reached ();
13704 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13706 g_assert_not_reached ();
13709 MonoReflectionModule *
13710 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13712 g_assert_not_reached ();
13717 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13719 g_assert_not_reached ();
13724 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13726 g_assert_not_reached ();
13731 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13732 gboolean create_open_instance, gboolean register_token, MonoError *error)
13734 g_assert_not_reached ();
13739 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13744 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13746 g_assert_not_reached ();
13750 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13753 *num_overrides = 0;
13756 MonoReflectionEvent *
13757 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13759 g_assert_not_reached ();
13763 MonoReflectionType*
13764 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13766 g_assert_not_reached ();
13771 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13773 g_assert_not_reached ();
13777 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13779 g_assert_not_reached ();
13784 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13786 g_assert_not_reached ();
13791 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13796 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13802 mono_reflection_type_get_handle (MonoReflectionType* ref)
13810 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13812 g_assert_not_reached ();
13815 #endif /* DISABLE_REFLECTION_EMIT */
13817 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13818 const static guint32 declsec_flags_map[] = {
13819 0x00000000, /* empty */
13820 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13821 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13822 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13823 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13824 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13825 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13826 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13827 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13828 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13829 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13830 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13831 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13832 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13833 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13834 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13835 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13836 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13837 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13841 * Returns flags that includes all available security action associated to the handle.
13842 * @token: metadata token (either for a class or a method)
13843 * @image: image where resides the metadata.
13846 mono_declsec_get_flags (MonoImage *image, guint32 token)
13848 int index = mono_metadata_declsec_from_index (image, token);
13849 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13850 guint32 result = 0;
13854 /* HasSecurity can be present for other, not specially encoded, attributes,
13855 e.g. SuppressUnmanagedCodeSecurityAttribute */
13859 for (i = index; i < t->rows; i++) {
13860 guint32 cols [MONO_DECL_SECURITY_SIZE];
13862 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13863 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13866 action = cols [MONO_DECL_SECURITY_ACTION];
13867 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13868 result |= declsec_flags_map [action];
13870 g_assert_not_reached ();
13877 * Get the security actions (in the form of flags) associated with the specified method.
13879 * @method: The method for which we want the declarative security flags.
13880 * Return the declarative security flags for the method (only).
13882 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13883 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13886 mono_declsec_flags_from_method (MonoMethod *method)
13888 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13889 /* FIXME: No cache (for the moment) */
13890 guint32 idx = mono_method_get_index (method);
13891 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13892 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13893 return mono_declsec_get_flags (method->klass->image, idx);
13899 * Get the security actions (in the form of flags) associated with the specified class.
13901 * @klass: The class for which we want the declarative security flags.
13902 * Return the declarative security flags for the class.
13904 * Note: We cache the flags inside the MonoClass structure as this will get
13905 * called very often (at least for each method).
13908 mono_declsec_flags_from_class (MonoClass *klass)
13910 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13911 if (!klass->ext || !klass->ext->declsec_flags) {
13914 idx = mono_metadata_token_index (klass->type_token);
13915 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13916 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13917 mono_loader_lock ();
13918 mono_class_alloc_ext (klass);
13919 mono_loader_unlock ();
13920 /* we cache the flags on classes */
13921 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13923 return klass->ext->declsec_flags;
13929 * Get the security actions (in the form of flags) associated with the specified assembly.
13931 * @assembly: The assembly for which we want the declarative security flags.
13932 * Return the declarative security flags for the assembly.
13935 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13937 guint32 idx = 1; /* there is only one assembly */
13938 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13939 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13940 return mono_declsec_get_flags (assembly->image, idx);
13945 * Fill actions for the specific index (which may either be an encoded class token or
13946 * an encoded method token) from the metadata image.
13947 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13950 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13951 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13953 MonoBoolean result = FALSE;
13955 guint32 cols [MONO_DECL_SECURITY_SIZE];
13956 int index = mono_metadata_declsec_from_index (image, token);
13959 t = &image->tables [MONO_TABLE_DECLSECURITY];
13960 for (i = index; i < t->rows; i++) {
13961 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13963 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13966 /* if present only replace (class) permissions with method permissions */
13967 /* if empty accept either class or method permissions */
13968 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13969 if (!actions->demand.blob) {
13970 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13971 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13972 actions->demand.blob = (char*) (blob + 2);
13973 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13976 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13977 if (!actions->noncasdemand.blob) {
13978 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13979 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13980 actions->noncasdemand.blob = (char*) (blob + 2);
13981 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13984 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13985 if (!actions->demandchoice.blob) {
13986 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13987 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13988 actions->demandchoice.blob = (char*) (blob + 2);
13989 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13999 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14000 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14002 guint32 idx = mono_metadata_token_index (klass->type_token);
14003 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14004 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14005 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14009 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14010 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14012 guint32 idx = mono_method_get_index (method);
14013 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14014 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14015 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14019 * Collect all actions (that requires to generate code in mini) assigned for
14020 * the specified method.
14021 * Note: Don't use the content of actions if the function return FALSE.
14024 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14026 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14027 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14028 MonoBoolean result = FALSE;
14031 /* quick exit if no declarative security is present in the metadata */
14032 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14035 /* we want the original as the wrapper is "free" of the security informations */
14036 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14037 method = mono_marshal_method_from_wrapper (method);
14042 /* First we look for method-level attributes */
14043 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14044 mono_class_init (method->klass);
14045 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14047 result = mono_declsec_get_method_demands_params (method, demands,
14048 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14051 /* Here we use (or create) the class declarative cache to look for demands */
14052 flags = mono_declsec_flags_from_class (method->klass);
14053 if (flags & mask) {
14055 mono_class_init (method->klass);
14056 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14058 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14059 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14062 /* The boolean return value is used as a shortcut in case nothing needs to
14063 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14069 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14071 * Note: Don't use the content of actions if the function return FALSE.
14074 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14076 MonoBoolean result = FALSE;
14079 /* quick exit if no declarative security is present in the metadata */
14080 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14083 /* we want the original as the wrapper is "free" of the security informations */
14084 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14085 method = mono_marshal_method_from_wrapper (method);
14090 /* results are independant - zeroize both */
14091 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14092 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14094 /* First we look for method-level attributes */
14095 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14096 mono_class_init (method->klass);
14098 result = mono_declsec_get_method_demands_params (method, cmethod,
14099 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14102 /* Here we use (or create) the class declarative cache to look for demands */
14103 flags = mono_declsec_flags_from_class (method->klass);
14104 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14105 mono_class_init (method->klass);
14107 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14108 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14115 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14117 * @klass The inherited class - this is the class that provides the security check (attributes)
14119 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14121 * Note: Don't use the content of actions if the function return FALSE.
14124 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14126 MonoBoolean result = FALSE;
14129 /* quick exit if no declarative security is present in the metadata */
14130 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14133 /* Here we use (or create) the class declarative cache to look for demands */
14134 flags = mono_declsec_flags_from_class (klass);
14135 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14136 mono_class_init (klass);
14137 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14139 result |= mono_declsec_get_class_demands_params (klass, demands,
14140 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14147 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14149 * Note: Don't use the content of actions if the function return FALSE.
14152 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14154 /* quick exit if no declarative security is present in the metadata */
14155 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14158 /* we want the original as the wrapper is "free" of the security informations */
14159 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14160 method = mono_marshal_method_from_wrapper (method);
14165 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14166 mono_class_init (method->klass);
14167 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14169 return mono_declsec_get_method_demands_params (method, demands,
14170 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14177 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14179 guint32 cols [MONO_DECL_SECURITY_SIZE];
14183 int index = mono_metadata_declsec_from_index (image, token);
14187 t = &image->tables [MONO_TABLE_DECLSECURITY];
14188 for (i = index; i < t->rows; i++) {
14189 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14191 /* shortcut - index are ordered */
14192 if (token != cols [MONO_DECL_SECURITY_PARENT])
14195 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14196 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14197 entry->blob = (char*) (metadata + 2);
14198 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14207 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14209 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14210 guint32 idx = mono_method_get_index (method);
14211 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14212 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14213 return get_declsec_action (method->klass->image, idx, action, entry);
14219 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14222 guint32 flags = mono_declsec_flags_from_class (klass);
14223 if (declsec_flags_map [action] & flags) {
14224 guint32 idx = mono_metadata_token_index (klass->type_token);
14225 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14226 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14227 return get_declsec_action (klass->image, idx, action, entry);
14233 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14235 guint32 idx = 1; /* there is only one assembly */
14236 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14237 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14239 return get_declsec_action (assembly->image, idx, action, entry);
14243 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14246 MonoObject *res, *exc;
14248 static MonoMethod *method = NULL;
14250 if (method == NULL) {
14251 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14256 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14257 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14259 g_assert (mono_class_get_ref_info (klass));
14260 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14262 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14263 mono_error_raise_exception (&error); /* FIXME don't raise here */
14265 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14267 if (exc || !mono_error_ok (&error)) {
14268 mono_error_cleanup (&error);
14271 return *(MonoBoolean*)mono_object_unbox (res);
14275 * mono_reflection_type_get_type:
14276 * @reftype: the System.Type object
14278 * Returns the MonoType* associated with the C# System.Type object @reftype.
14281 mono_reflection_type_get_type (MonoReflectionType *reftype)
14283 g_assert (reftype);
14286 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14287 mono_error_assert_ok (&error);
14292 * mono_reflection_assembly_get_assembly:
14293 * @refassembly: the System.Reflection.Assembly object
14295 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14298 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14300 g_assert (refassembly);
14302 return refassembly->assembly;