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, MonoError *error);
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, MonoError *error);
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, MonoError *error)
2476 MONO_REQ_GC_UNSAFE_MODE;
2478 MonoDynamicTable *table;
2480 guint num_methods = 0;
2484 * we need to set things in the following tables:
2485 * EVENTMAP (info already filled in _get_type_info ())
2486 * EVENT (rows already preallocated in _get_type_info ())
2487 * METHOD (method info already done with the generic method code)
2490 table = &assembly->tables [MONO_TABLE_EVENT];
2491 eb->table_idx = table->next_idx ++;
2492 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2493 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2494 values [MONO_EVENT_FLAGS] = eb->attrs;
2495 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2496 return_if_nok (error);
2497 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2500 * FIXME: we still don't handle 'other' methods
2502 if (eb->add_method) num_methods ++;
2503 if (eb->remove_method) num_methods ++;
2504 if (eb->raise_method) num_methods ++;
2506 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2507 table->rows += num_methods;
2508 alloc_table (table, table->rows);
2510 if (eb->add_method) {
2511 semaidx = table->next_idx ++;
2512 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2513 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2514 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2515 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2517 if (eb->remove_method) {
2518 semaidx = table->next_idx ++;
2519 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2520 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2521 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2522 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2524 if (eb->raise_method) {
2525 semaidx = table->next_idx ++;
2526 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2527 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2528 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2529 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2534 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2536 MONO_REQ_GC_UNSAFE_MODE;
2538 mono_error_init (error);
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 return_if_nok (error);
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 return_if_nok (error);
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, error);
2631 return_val_if_nok (error, FALSE);
2637 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2639 MONO_REQ_GC_UNSAFE_MODE;
2641 MonoDynamicTable *table;
2644 guint32 cols [MONO_ASSEMBLY_SIZE];
2648 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2651 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2652 table = &assembly->tables [MONO_TABLE_MODULEREF];
2653 token = table->next_idx ++;
2655 alloc_table (table, table->rows);
2656 values = table->values + token * MONO_MODULEREF_SIZE;
2657 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2659 token <<= MONO_RESOLUTION_SCOPE_BITS;
2660 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2661 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2666 if (assembly_is_dynamic (image->assembly))
2668 memset (cols, 0, sizeof (cols));
2670 /* image->assembly->image is the manifest module */
2671 image = image->assembly->image;
2672 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2675 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2676 token = table->next_idx ++;
2678 alloc_table (table, table->rows);
2679 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2680 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2681 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2682 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2683 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2684 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2685 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2686 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2687 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2689 if (strcmp ("", image->assembly->aname.culture)) {
2690 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2691 image->assembly->aname.culture);
2694 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2695 guchar pubtoken [9];
2697 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2698 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2700 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2702 token <<= MONO_RESOLUTION_SCOPE_BITS;
2703 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2704 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2709 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2711 MONO_REQ_GC_NEUTRAL_MODE;
2713 MonoDynamicTable *table;
2718 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2721 sigbuffer_init (&buf, 32);
2722 switch (type->type) {
2723 case MONO_TYPE_FNPTR:
2725 case MONO_TYPE_SZARRAY:
2726 case MONO_TYPE_ARRAY:
2728 case MONO_TYPE_MVAR:
2729 case MONO_TYPE_GENERICINST:
2730 encode_type (assembly, type, &buf);
2732 case MONO_TYPE_CLASS:
2733 case MONO_TYPE_VALUETYPE: {
2734 MonoClass *k = mono_class_from_mono_type (type);
2735 if (!k || !k->generic_container) {
2736 sigbuffer_free (&buf);
2739 encode_type (assembly, type, &buf);
2743 sigbuffer_free (&buf);
2747 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2748 if (assembly->save) {
2749 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2750 alloc_table (table, table->rows + 1);
2751 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2752 values [MONO_TYPESPEC_SIGNATURE] = token;
2754 sigbuffer_free (&buf);
2756 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2757 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2763 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2765 MONO_REQ_GC_UNSAFE_MODE;
2767 MonoDynamicTable *table;
2769 guint32 token, scope, enclosing;
2772 /* if the type requires a typespec, we must try that first*/
2773 if (try_typespec && (token = create_typespec (assembly, type)))
2775 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2778 klass = mono_class_from_mono_type (type);
2780 klass = mono_class_from_mono_type (type);
2783 * If it's in the same module and not a generic type parameter:
2785 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2786 (type->type != MONO_TYPE_MVAR)) {
2787 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2788 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2789 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2793 if (klass->nested_in) {
2794 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2795 /* get the typeref idx of the enclosing type */
2796 enclosing >>= MONO_TYPEDEFORREF_BITS;
2797 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2799 scope = resolution_scope_from_image (assembly, klass->image);
2801 table = &assembly->tables [MONO_TABLE_TYPEREF];
2802 if (assembly->save) {
2803 alloc_table (table, table->rows + 1);
2804 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2805 values [MONO_TYPEREF_SCOPE] = scope;
2806 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2807 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2809 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2810 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2812 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2817 * Despite the name, we handle also TypeSpec (with the above helper).
2820 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2822 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2825 #ifndef DISABLE_REFLECTION_EMIT
2827 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2829 MONO_REQ_GC_NEUTRAL_MODE;
2831 MonoDynamicTable *table;
2833 guint32 token, pclass;
2835 switch (parent & MONO_TYPEDEFORREF_MASK) {
2836 case MONO_TYPEDEFORREF_TYPEREF:
2837 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2839 case MONO_TYPEDEFORREF_TYPESPEC:
2840 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2842 case MONO_TYPEDEFORREF_TYPEDEF:
2843 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2846 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2849 /* extract the index */
2850 parent >>= MONO_TYPEDEFORREF_BITS;
2852 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2854 if (assembly->save) {
2855 alloc_table (table, table->rows + 1);
2856 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2857 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2858 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2859 values [MONO_MEMBERREF_SIGNATURE] = sig;
2862 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2869 * Insert a memberef row into the metadata: the token that point to the memberref
2870 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2871 * mono_image_get_fieldref_token()).
2872 * The sig param is an index to an already built signature.
2875 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2877 MONO_REQ_GC_NEUTRAL_MODE;
2879 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2880 return mono_image_add_memberef_row (assembly, parent, name, sig);
2885 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2887 MONO_REQ_GC_NEUTRAL_MODE;
2890 MonoMethodSignature *sig;
2892 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2894 if (create_typespec) {
2895 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2900 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2901 if (token && !create_typespec)
2904 g_assert (!method->is_inflated);
2907 * A methodref signature can't contain an unmanaged calling convention.
2909 sig = mono_metadata_signature_dup (mono_method_signature (method));
2910 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2911 sig->call_convention = MONO_CALL_DEFAULT;
2912 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2913 method->name, method_encode_signature (assembly, sig));
2915 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2918 if (create_typespec) {
2919 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2920 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2921 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2923 if (assembly->save) {
2926 alloc_table (table, table->rows + 1);
2927 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2928 values [MONO_METHODSPEC_METHOD] = token;
2929 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2932 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2934 /*methodspec and memberef tokens are diferent, */
2935 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2942 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2944 guint32 token, parent, sig;
2945 ReflectionMethodBuilder rmb;
2946 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2948 mono_error_init (error);
2949 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2953 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2957 * A methodref signature can't contain an unmanaged calling convention.
2958 * Since some flags are encoded as part of call_conv, we need to check against it.
2960 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2961 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2963 sig = method_builder_encode_signature (assembly, &rmb, error);
2964 return_val_if_nok (error, 0);
2966 if (tb->generic_params) {
2967 parent = create_generic_typespec (assembly, tb, error);
2968 return_val_if_nok (error, 0);
2970 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2971 return_val_if_nok (error, 0);
2973 parent = mono_image_typedef_or_ref (assembly, t);
2976 char *name = mono_string_to_utf8 (method->name);
2978 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2981 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2987 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2988 const gchar *name, guint32 sig)
2990 MonoDynamicTable *table;
2994 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2996 if (assembly->save) {
2997 alloc_table (table, table->rows + 1);
2998 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2999 values [MONO_MEMBERREF_CLASS] = original;
3000 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3001 values [MONO_MEMBERREF_SIGNATURE] = sig;
3004 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3011 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3015 guint32 nparams = mono_array_length (mb->generic_params);
3018 if (!assembly->save)
3021 sigbuffer_init (&buf, 32);
3023 sigbuffer_add_value (&buf, 0xa);
3024 sigbuffer_add_value (&buf, nparams);
3026 for (i = 0; i < nparams; i++) {
3027 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3028 sigbuffer_add_value (&buf, i);
3031 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3032 sigbuffer_free (&buf);
3037 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3039 MonoDynamicTable *table;
3041 guint32 token, mtoken = 0;
3043 mono_error_init (error);
3044 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3048 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3050 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3051 if (!mono_error_ok (error))
3054 switch (mono_metadata_token_table (mtoken)) {
3055 case MONO_TABLE_MEMBERREF:
3056 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3058 case MONO_TABLE_METHOD:
3059 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3062 g_assert_not_reached ();
3065 if (assembly->save) {
3066 alloc_table (table, table->rows + 1);
3067 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3068 values [MONO_METHODSPEC_METHOD] = mtoken;
3069 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3072 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3075 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3080 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3084 mono_error_init (error);
3086 if (mb->generic_params && create_methodspec)
3087 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3089 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3093 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3094 if (!mono_error_ok (error))
3096 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3101 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3103 guint32 token, parent, sig;
3104 ReflectionMethodBuilder rmb;
3106 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3108 mono_error_init (error);
3110 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3114 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3117 if (tb->generic_params) {
3118 parent = create_generic_typespec (assembly, tb, error);
3119 return_val_if_nok (error, 0);
3121 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3122 return_val_if_nok (error, 0);
3123 parent = mono_image_typedef_or_ref (assembly, type);
3126 name = mono_string_to_utf8 (rmb.name);
3127 sig = method_builder_encode_signature (assembly, &rmb, error);
3128 return_val_if_nok (error, 0);
3130 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3133 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3139 is_field_on_inst (MonoClassField *field)
3141 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3145 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3148 get_field_on_inst_generic_type (MonoClassField *field)
3150 MonoClass *klass, *gtd;
3151 MonoDynamicGenericClass *dgclass;
3154 g_assert (is_field_on_inst (field));
3156 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3158 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3159 field_index = field - dgclass->fields;
3160 return dgclass->field_generic_types [field_index];
3163 klass = field->parent;
3164 gtd = klass->generic_class->container_class;
3166 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3167 field_index = field - klass->fields;
3168 return gtd->fields [field_index].type;
3171 g_assert_not_reached ();
3175 #ifndef DISABLE_REFLECTION_EMIT
3177 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3183 g_assert (field->parent);
3185 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3189 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3190 int index = field - field->parent->fields;
3191 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3193 if (is_field_on_inst (field))
3194 type = get_field_on_inst_generic_type (field);
3196 type = mono_field_get_type (field);
3198 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3199 mono_field_get_name (field),
3200 fieldref_encode_signature (assembly, field->parent->image, type));
3201 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3206 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3210 MonoGenericClass *gclass;
3214 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3217 if (is_sre_field_builder (mono_object_class (f->fb))) {
3218 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3219 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3220 return_val_if_nok (error, 0);
3221 klass = mono_class_from_mono_type (type);
3222 gclass = type->data.generic_class;
3223 g_assert (gclass->is_dynamic);
3225 guint32 sig_token = field_encode_signature (assembly, fb, error);
3226 return_val_if_nok (error, 0);
3227 name = mono_string_to_utf8 (fb->name);
3228 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3230 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3232 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3234 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3235 return_val_if_nok (error, 0);
3236 klass = mono_class_from_mono_type (type);
3238 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3239 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3241 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3242 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3245 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3250 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3254 MonoGenericClass *gclass;
3257 mono_error_init (error);
3259 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3261 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3265 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3266 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3267 ReflectionMethodBuilder rmb;
3270 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3271 return_val_if_nok (error, 0);
3272 klass = mono_class_from_mono_type (type);
3274 gclass = type->data.generic_class;
3275 g_assert (gclass->is_dynamic);
3277 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3280 sig = method_builder_encode_signature (assembly, &rmb, error);
3281 return_val_if_nok (error, 0);
3283 name = mono_string_to_utf8 (rmb.name);
3285 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3287 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3288 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3290 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3291 return_val_if_nok (error, 0);
3292 klass = mono_class_from_mono_type (type);
3294 sig = method_encode_signature (assembly, mono_method_signature (mm));
3295 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3297 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3298 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3302 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3307 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3310 MonoGenericContext tmp_context;
3311 MonoType **type_argv;
3312 MonoGenericInst *ginst;
3313 MonoMethod *method, *inflated;
3316 mono_error_init (error);
3318 init_type_builder_generics ((MonoObject*)m->inst);
3320 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3321 return_val_if_nok (error, NULL);
3323 klass = method->klass;
3325 if (m->method_args == NULL)
3328 if (method->is_inflated)
3329 method = ((MonoMethodInflated *) method)->declaring;
3331 count = mono_array_length (m->method_args);
3333 type_argv = g_new0 (MonoType *, count);
3334 for (i = 0; i < count; i++) {
3335 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3336 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3337 return_val_if_nok (error, NULL);
3339 ginst = mono_metadata_get_generic_inst (count, type_argv);
3342 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3343 tmp_context.method_inst = ginst;
3345 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3346 mono_error_assert_ok (error);
3351 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3353 guint32 sig, token = 0;
3357 mono_error_init (error);
3359 if (m->method_args) {
3360 MonoMethod *inflated;
3362 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3363 return_val_if_nok (error, 0);
3365 if (create_methodspec)
3366 token = mono_image_get_methodspec_token (assembly, inflated);
3368 token = mono_image_get_inflated_method_token (assembly, inflated);
3372 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3376 if (is_sre_method_builder (mono_object_class (m->mb))) {
3377 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3378 MonoGenericClass *gclass;
3379 ReflectionMethodBuilder rmb;
3382 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3383 return_val_if_nok (error, 0);
3384 klass = mono_class_from_mono_type (type);
3385 gclass = type->data.generic_class;
3386 g_assert (gclass->is_dynamic);
3388 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3391 sig = method_builder_encode_signature (assembly, &rmb, error);
3392 return_val_if_nok (error, 0);
3394 name = mono_string_to_utf8 (rmb.name);
3396 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3398 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3399 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3401 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3402 return_val_if_nok (error, 0);
3403 klass = mono_class_from_mono_type (type);
3405 sig = method_encode_signature (assembly, mono_method_signature (mm));
3406 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3408 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3409 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3412 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3417 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3421 guint32 nparams = context->method_inst->type_argc;
3424 if (!assembly->save)
3427 sigbuffer_init (&buf, 32);
3429 * FIXME: vararg, explicit_this, differenc call_conv values...
3431 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3432 sigbuffer_add_value (&buf, nparams);
3434 for (i = 0; i < nparams; i++)
3435 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3437 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3438 sigbuffer_free (&buf);
3443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3445 MonoDynamicTable *table;
3447 guint32 token, mtoken = 0, sig;
3448 MonoMethodInflated *imethod;
3449 MonoMethod *declaring;
3451 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3453 g_assert (method->is_inflated);
3454 imethod = (MonoMethodInflated *) method;
3455 declaring = imethod->declaring;
3457 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3458 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3460 if (!mono_method_signature (declaring)->generic_param_count)
3463 switch (mono_metadata_token_table (mtoken)) {
3464 case MONO_TABLE_MEMBERREF:
3465 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3467 case MONO_TABLE_METHOD:
3468 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3471 g_assert_not_reached ();
3474 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3476 if (assembly->save) {
3477 alloc_table (table, table->rows + 1);
3478 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3479 values [MONO_METHODSPEC_METHOD] = mtoken;
3480 values [MONO_METHODSPEC_SIGNATURE] = sig;
3483 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3490 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3492 MonoMethodInflated *imethod;
3495 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3499 g_assert (method->is_inflated);
3500 imethod = (MonoMethodInflated *) method;
3502 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3503 token = method_encode_methodspec (assembly, method);
3505 guint32 sig = method_encode_signature (
3506 assembly, mono_method_signature (imethod->declaring));
3507 token = mono_image_get_memberref_token (
3508 assembly, &method->klass->byval_arg, method->name, sig);
3511 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3516 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3518 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3521 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3522 token = mono_image_get_memberref_token (
3523 assembly, &m->klass->byval_arg, m->name, sig);
3529 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3531 MonoDynamicTable *table;
3540 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3541 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3542 * Because of this, we must not insert it into the `typeref' hash table.
3544 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3545 return_val_if_nok (error, 0);
3546 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3550 sigbuffer_init (&buf, 32);
3552 g_assert (tb->generic_params);
3553 klass = mono_class_from_mono_type (type);
3555 if (tb->generic_container)
3556 mono_reflection_create_generic_class (tb);
3558 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3559 g_assert (klass->generic_container);
3560 sigbuffer_add_value (&buf, klass->byval_arg.type);
3561 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3563 count = mono_array_length (tb->generic_params);
3564 sigbuffer_add_value (&buf, count);
3565 for (i = 0; i < count; i++) {
3566 MonoReflectionGenericParam *gparam;
3568 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3569 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3573 encode_type (assembly, gparam_type, &buf);
3576 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3578 if (assembly->save) {
3579 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3580 alloc_table (table, table->rows + 1);
3581 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3582 values [MONO_TYPESPEC_SIGNATURE] = token;
3584 sigbuffer_free (&buf);
3586 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3587 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3591 sigbuffer_free (&buf);
3596 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3599 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3601 int i, count, len, pos;
3604 mono_error_init (error);
3608 count += mono_array_length (modreq);
3610 count += mono_array_length (modopt);
3613 return mono_metadata_type_dup (NULL, type);
3615 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3616 t = (MonoType *)g_malloc (len);
3617 memcpy (t, type, MONO_SIZEOF_TYPE);
3619 t->num_mods = count;
3622 for (i = 0; i < mono_array_length (modreq); ++i) {
3623 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3626 t->modifiers [pos].required = 1;
3627 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3632 for (i = 0; i < mono_array_length (modopt); ++i) {
3633 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3636 t->modifiers [pos].required = 0;
3637 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3649 init_type_builder_generics (MonoObject *type)
3651 MonoReflectionTypeBuilder *tb;
3653 if (!is_sre_type_builder(mono_object_class (type)))
3655 tb = (MonoReflectionTypeBuilder *)type;
3657 if (tb && tb->generic_container)
3658 mono_reflection_create_generic_class (tb);
3662 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3664 MonoDynamicTable *table;
3665 MonoType *custom = NULL, *type;
3667 guint32 token, pclass, parent, sig;
3670 mono_error_init (error);
3672 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3676 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3677 return_val_if_nok (error, 0);
3678 /* FIXME: is this call necessary? */
3679 mono_class_from_mono_type (typeb);
3681 /*FIXME this is one more layer of ugliness due how types are created.*/
3682 init_type_builder_generics (fb->type);
3684 /* fb->type does not include the custom modifiers */
3685 /* FIXME: We should do this in one place when a fieldbuilder is created */
3686 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3687 return_val_if_nok (error, 0);
3689 if (fb->modreq || fb->modopt) {
3690 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3691 return_val_if_nok (error, 0);
3694 sig = fieldref_encode_signature (assembly, NULL, type);
3697 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3698 return_val_if_nok (error, 0);
3699 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3701 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3702 parent >>= MONO_TYPEDEFORREF_BITS;
3704 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3706 name = mono_string_to_utf8 (fb->name);
3708 if (assembly->save) {
3709 alloc_table (table, table->rows + 1);
3710 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3711 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3712 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3713 values [MONO_MEMBERREF_SIGNATURE] = sig;
3716 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3718 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3724 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3730 mono_error_init (error);
3732 if (!assembly->save)
3735 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3736 g_assert (helper->type == 2);
3738 if (helper->arguments)
3739 nargs = mono_array_length (helper->arguments);
3743 sigbuffer_init (&buf, 32);
3745 /* Encode calling convention */
3746 /* Change Any to Standard */
3747 if ((helper->call_conv & 0x03) == 0x03)
3748 helper->call_conv = 0x01;
3749 /* explicit_this implies has_this */
3750 if (helper->call_conv & 0x40)
3751 helper->call_conv &= 0x20;
3753 if (helper->call_conv == 0) { /* Unmanaged */
3754 idx = helper->unmanaged_call_conv - 1;
3757 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3758 if (helper->call_conv & 0x02) /* varargs */
3762 sigbuffer_add_byte (&buf, idx);
3763 sigbuffer_add_value (&buf, nargs);
3764 encode_reflection_type (assembly, helper->return_type, &buf, error);
3767 for (i = 0; i < nargs; ++i) {
3768 MonoArray *modreqs = NULL;
3769 MonoArray *modopts = NULL;
3770 MonoReflectionType *pt;
3772 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3773 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3774 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3775 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3777 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3780 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3781 encode_reflection_type (assembly, pt, &buf, error);
3785 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3786 sigbuffer_free (&buf);
3790 sigbuffer_free (&buf);
3795 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3798 MonoDynamicTable *table;
3801 mono_error_init (error);
3803 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3804 idx = table->next_idx ++;
3806 alloc_table (table, table->rows);
3807 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3809 values [MONO_STAND_ALONE_SIGNATURE] =
3810 mono_reflection_encode_sighelper (assembly, helper, error);
3811 return_val_if_nok (error, 0);
3817 reflection_cc_to_file (int call_conv) {
3818 switch (call_conv & 0x3) {
3820 case 1: return MONO_CALL_DEFAULT;
3821 case 2: return MONO_CALL_VARARG;
3823 g_assert_not_reached ();
3827 #endif /* !DISABLE_REFLECTION_EMIT */
3831 MonoMethodSignature *sig;
3836 #ifndef DISABLE_REFLECTION_EMIT
3838 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3843 MonoMethodSignature *sig;
3844 ArrayMethod *am = NULL;
3847 mono_error_init (error);
3849 nparams = mono_array_length (m->parameters);
3850 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3852 sig->sentinelpos = -1;
3853 sig->call_convention = reflection_cc_to_file (m->call_conv);
3854 sig->param_count = nparams;
3856 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3860 sig->ret = &mono_defaults.void_class->byval_arg;
3862 mtype = mono_reflection_type_get_handle (m->parent, error);
3866 for (i = 0; i < nparams; ++i) {
3867 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3872 name = mono_string_to_utf8 (m->name);
3873 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3874 am = (ArrayMethod *)tmp->data;
3875 if (strcmp (name, am->name) == 0 &&
3876 mono_metadata_type_equal (am->parent, mtype) &&
3877 mono_metadata_signature_equal (am->sig, sig)) {
3880 m->table_idx = am->token & 0xffffff;
3884 am = g_new0 (ArrayMethod, 1);
3888 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3889 method_encode_signature (assembly, sig));
3890 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3891 m->table_idx = am->token & 0xffffff;
3902 * Insert into the metadata tables all the info about the TypeBuilder tb.
3903 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3906 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3908 MonoDynamicTable *table;
3910 int i, is_object = 0, is_system = 0;
3913 mono_error_init (error);
3915 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3916 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3917 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3918 n = mono_string_to_utf8 (tb->name);
3919 if (strcmp (n, "Object") == 0)
3921 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3923 n = mono_string_to_utf8 (tb->nspace);
3924 if (strcmp (n, "System") == 0)
3926 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3928 if (tb->parent && !(is_system && is_object) &&
3929 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3930 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3931 return_val_if_nok (error, FALSE);
3932 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3934 values [MONO_TYPEDEF_EXTENDS] = 0;
3936 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3937 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3940 * if we have explicitlayout or sequentiallayouts, output data in the
3941 * ClassLayout table.
3943 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3944 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3945 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3947 alloc_table (table, table->rows);
3948 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3949 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3950 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3951 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3954 /* handle interfaces */
3955 if (tb->interfaces) {
3956 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3958 table->rows += mono_array_length (tb->interfaces);
3959 alloc_table (table, table->rows);
3960 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3961 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3962 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3963 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3964 return_val_if_nok (error, FALSE);
3965 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3966 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3967 values += MONO_INTERFACEIMPL_SIZE;
3973 table = &assembly->tables [MONO_TABLE_FIELD];
3974 table->rows += tb->num_fields;
3975 alloc_table (table, table->rows);
3976 for (i = 0; i < tb->num_fields; ++i) {
3977 mono_image_get_field_info (
3978 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3979 return_val_if_nok (error, FALSE);
3983 /* handle constructors */
3985 table = &assembly->tables [MONO_TABLE_METHOD];
3986 table->rows += mono_array_length (tb->ctors);
3987 alloc_table (table, table->rows);
3988 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3989 if (!mono_image_get_ctor_info (domain,
3990 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3996 /* handle methods */
3998 table = &assembly->tables [MONO_TABLE_METHOD];
3999 table->rows += tb->num_methods;
4000 alloc_table (table, table->rows);
4001 for (i = 0; i < tb->num_methods; ++i) {
4002 if (!mono_image_get_method_info (
4003 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4008 /* Do the same with properties etc.. */
4009 if (tb->events && mono_array_length (tb->events)) {
4010 table = &assembly->tables [MONO_TABLE_EVENT];
4011 table->rows += mono_array_length (tb->events);
4012 alloc_table (table, table->rows);
4013 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4015 alloc_table (table, table->rows);
4016 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4017 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4018 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4019 for (i = 0; i < mono_array_length (tb->events); ++i) {
4020 mono_image_get_event_info (
4021 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4022 return_val_if_nok (error, FALSE);
4025 if (tb->properties && mono_array_length (tb->properties)) {
4026 table = &assembly->tables [MONO_TABLE_PROPERTY];
4027 table->rows += mono_array_length (tb->properties);
4028 alloc_table (table, table->rows);
4029 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4031 alloc_table (table, table->rows);
4032 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4033 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4034 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4035 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4036 mono_image_get_property_info (
4037 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4038 return_val_if_nok (error, FALSE);
4042 /* handle generic parameters */
4043 if (tb->generic_params) {
4044 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4045 table->rows += mono_array_length (tb->generic_params);
4046 alloc_table (table, table->rows);
4047 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4048 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4050 mono_image_get_generic_param_info (
4051 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4055 mono_image_add_decl_security (assembly,
4056 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4059 MonoDynamicTable *ntable;
4061 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4062 ntable->rows += mono_array_length (tb->subtypes);
4063 alloc_table (ntable, ntable->rows);
4064 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4066 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4067 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4069 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4070 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4071 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4072 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4073 mono_string_to_utf8 (tb->name), tb->table_idx,
4074 ntable->next_idx, ntable->rows);*/
4075 values += MONO_NESTED_CLASS_SIZE;
4085 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4089 mono_ptr_array_append (*types, type);
4091 if (!type->subtypes)
4094 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4095 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4096 collect_types (types, subtype);
4101 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4103 if ((*type1)->table_idx < (*type2)->table_idx)
4106 if ((*type1)->table_idx > (*type2)->table_idx)
4113 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4116 mono_error_init (error);
4119 for (i = 0; i < mono_array_length (pinfo); ++i) {
4120 MonoReflectionParamBuilder *pb;
4121 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4124 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4132 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4135 mono_error_init (error);
4137 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4140 for (i = 0; i < tb->num_fields; ++i) {
4141 MonoReflectionFieldBuilder* fb;
4142 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4143 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4148 for (i = 0; i < mono_array_length (tb->events); ++i) {
4149 MonoReflectionEventBuilder* eb;
4150 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4151 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4155 if (tb->properties) {
4156 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4157 MonoReflectionPropertyBuilder* pb;
4158 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4159 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4164 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4165 MonoReflectionCtorBuilder* cb;
4166 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4167 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4168 !params_add_cattrs (assembly, cb->pinfo, error))
4174 for (i = 0; i < tb->num_methods; ++i) {
4175 MonoReflectionMethodBuilder* mb;
4176 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4177 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4178 !params_add_cattrs (assembly, mb->pinfo, error))
4184 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4185 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4194 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4198 mono_error_init (error);
4200 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4203 if (moduleb->global_methods) {
4204 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4205 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4206 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4207 !params_add_cattrs (assembly, mb->pinfo, error))
4212 if (moduleb->global_fields) {
4213 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4214 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4215 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4220 if (moduleb->types) {
4221 for (i = 0; i < moduleb->num_types; ++i) {
4222 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4231 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4233 MonoDynamicTable *table;
4237 char *b = blob_size;
4240 table = &assembly->tables [MONO_TABLE_FILE];
4242 alloc_table (table, table->rows);
4243 values = table->values + table->next_idx * MONO_FILE_SIZE;
4244 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4245 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4246 if (image_is_dynamic (module->image)) {
4247 /* This depends on the fact that the main module is emitted last */
4248 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4249 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4252 path = g_strdup (module->image->name);
4254 mono_sha1_get_digest_from_file (path, hash);
4257 mono_metadata_encode_value (20, b, &b);
4258 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4259 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4264 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4266 MonoDynamicTable *table;
4269 table = &assembly->tables [MONO_TABLE_MODULE];
4270 mb->table_idx = table->next_idx ++;
4271 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4272 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4275 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4276 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4277 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4278 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4282 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4283 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4285 MonoDynamicTable *table;
4289 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4290 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4293 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4295 alloc_table (table, table->rows);
4296 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4298 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4299 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4300 if (klass->nested_in)
4301 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4303 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4304 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4305 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4307 res = table->next_idx;
4311 /* Emit nested types */
4312 if (klass->ext && klass->ext->nested_classes) {
4315 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4316 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4323 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4324 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4330 mono_error_init (error);
4332 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4333 return_if_nok (error);
4335 klass = mono_class_from_mono_type (t);
4337 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4339 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4340 parent_index, assembly);
4344 * We need to do this ourselves since klass->nested_classes is not set up.
4347 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4348 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4349 return_if_nok (error);
4355 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4356 guint32 module_index, MonoDynamicImage *assembly)
4358 MonoImage *image = module->image;
4362 t = &image->tables [MONO_TABLE_TYPEDEF];
4364 for (i = 0; i < t->rows; ++i) {
4366 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4367 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4369 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4370 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4375 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4377 MonoDynamicTable *table;
4379 guint32 scope, scope_idx, impl, current_idx;
4380 gboolean forwarder = TRUE;
4381 gpointer iter = NULL;
4384 if (klass->nested_in) {
4385 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4388 scope = resolution_scope_from_image (assembly, klass->image);
4389 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4390 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4391 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4394 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4397 alloc_table (table, table->rows);
4398 current_idx = table->next_idx;
4399 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4401 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4402 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4403 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4404 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4405 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4409 while ((nested = mono_class_get_nested_types (klass, &iter)))
4410 add_exported_type (assemblyb, assembly, nested, current_idx);
4414 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4420 if (!assemblyb->type_forwarders)
4423 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4424 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4429 type = mono_reflection_type_get_handle (t, &error);
4430 mono_error_assert_ok (&error);
4433 klass = mono_class_from_mono_type (type);
4435 add_exported_type (assemblyb, assembly, klass, 0);
4439 #define align_pointer(base,p)\
4441 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4443 (p) += 4 - (__diff & 3);\
4447 compare_constants (const void *a, const void *b)
4449 const guint32 *a_values = (const guint32 *)a;
4450 const guint32 *b_values = (const guint32 *)b;
4451 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4455 compare_semantics (const void *a, const void *b)
4457 const guint32 *a_values = (const guint32 *)a;
4458 const guint32 *b_values = (const guint32 *)b;
4459 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4462 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4466 compare_custom_attrs (const void *a, const void *b)
4468 const guint32 *a_values = (const guint32 *)a;
4469 const guint32 *b_values = (const guint32 *)b;
4471 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4475 compare_field_marshal (const void *a, const void *b)
4477 const guint32 *a_values = (const guint32 *)a;
4478 const guint32 *b_values = (const guint32 *)b;
4480 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4484 compare_nested (const void *a, const void *b)
4486 const guint32 *a_values = (const guint32 *)a;
4487 const guint32 *b_values = (const guint32 *)b;
4489 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4493 compare_genericparam (const void *a, const void *b)
4496 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4497 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4499 if ((*b_entry)->owner == (*a_entry)->owner) {
4500 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4501 mono_error_assert_ok (&error);
4502 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4503 mono_error_assert_ok (&error);
4505 mono_type_get_generic_param_num (a_type) -
4506 mono_type_get_generic_param_num (b_type);
4508 return (*a_entry)->owner - (*b_entry)->owner;
4512 compare_declsecurity_attrs (const void *a, const void *b)
4514 const guint32 *a_values = (const guint32 *)a;
4515 const guint32 *b_values = (const guint32 *)b;
4517 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4521 compare_interface_impl (const void *a, const void *b)
4523 const guint32 *a_values = (const guint32 *)a;
4524 const guint32 *b_values = (const guint32 *)b;
4526 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4530 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4534 pad_heap (MonoDynamicStream *sh)
4536 if (sh->index & 3) {
4537 int sz = 4 - (sh->index & 3);
4538 memset (sh->data + sh->index, 0, sz);
4545 MonoDynamicStream *stream;
4549 * build_compressed_metadata() fills in the blob of data that represents the
4550 * raw metadata as it will be saved in the PE file. The five streams are output
4551 * and the metadata tables are comnpressed from the guint32 array representation,
4552 * to the compressed on-disk format.
4555 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4557 MonoDynamicTable *table;
4559 guint64 valid_mask = 0;
4560 guint64 sorted_mask;
4561 guint32 heapt_size = 0;
4562 guint32 meta_size = 256; /* allow for header and other stuff */
4563 guint32 table_offset;
4564 guint32 ntables = 0;
4570 struct StreamDesc stream_desc [5];
4572 mono_error_init (error);
4574 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4575 for (i = 0; i < assembly->gen_params->len; i++) {
4576 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4577 if (!write_generic_param_entry (assembly, entry, error))
4581 stream_desc [0].name = "#~";
4582 stream_desc [0].stream = &assembly->tstream;
4583 stream_desc [1].name = "#Strings";
4584 stream_desc [1].stream = &assembly->sheap;
4585 stream_desc [2].name = "#US";
4586 stream_desc [2].stream = &assembly->us;
4587 stream_desc [3].name = "#Blob";
4588 stream_desc [3].stream = &assembly->blob;
4589 stream_desc [4].name = "#GUID";
4590 stream_desc [4].stream = &assembly->guid;
4592 /* tables that are sorted */
4593 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4594 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4595 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4596 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4597 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4598 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4599 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4601 /* Compute table sizes */
4602 /* the MonoImage has already been created in mono_image_basic_init() */
4603 meta = &assembly->image;
4605 /* sizes should be multiple of 4 */
4606 pad_heap (&assembly->blob);
4607 pad_heap (&assembly->guid);
4608 pad_heap (&assembly->sheap);
4609 pad_heap (&assembly->us);
4611 /* Setup the info used by compute_sizes () */
4612 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4613 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4614 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4616 meta_size += assembly->blob.index;
4617 meta_size += assembly->guid.index;
4618 meta_size += assembly->sheap.index;
4619 meta_size += assembly->us.index;
4621 for (i=0; i < MONO_TABLE_NUM; ++i)
4622 meta->tables [i].rows = assembly->tables [i].rows;
4624 for (i = 0; i < MONO_TABLE_NUM; i++){
4625 if (meta->tables [i].rows == 0)
4627 valid_mask |= (guint64)1 << i;
4629 meta->tables [i].row_size = mono_metadata_compute_size (
4630 meta, i, &meta->tables [i].size_bitfield);
4631 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4633 heapt_size += 24; /* #~ header size */
4634 heapt_size += ntables * 4;
4635 /* make multiple of 4 */
4638 meta_size += heapt_size;
4639 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4640 p = (unsigned char*)meta->raw_metadata;
4641 /* the metadata signature */
4642 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4643 /* version numbers and 4 bytes reserved */
4644 int16val = (guint16*)p;
4645 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4646 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4648 /* version string */
4649 int32val = (guint32*)p;
4650 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4652 memcpy (p, meta->version, strlen (meta->version));
4653 p += GUINT32_FROM_LE (*int32val);
4654 align_pointer (meta->raw_metadata, p);
4655 int16val = (guint16*)p;
4656 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4657 *int16val = GUINT16_TO_LE (5); /* number of streams */
4661 * write the stream info.
4663 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4664 table_offset += 3; table_offset &= ~3;
4666 assembly->tstream.index = heapt_size;
4667 for (i = 0; i < 5; ++i) {
4668 int32val = (guint32*)p;
4669 stream_desc [i].stream->offset = table_offset;
4670 *int32val++ = GUINT32_TO_LE (table_offset);
4671 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4672 table_offset += GUINT32_FROM_LE (*int32val);
4673 table_offset += 3; table_offset &= ~3;
4675 strcpy ((char*)p, stream_desc [i].name);
4676 p += strlen (stream_desc [i].name) + 1;
4677 align_pointer (meta->raw_metadata, p);
4680 * now copy the data, the table stream header and contents goes first.
4682 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4683 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4684 int32val = (guint32*)p;
4685 *int32val = GUINT32_TO_LE (0); /* reserved */
4688 *p++ = 2; /* version */
4691 if (meta->idx_string_wide)
4693 if (meta->idx_guid_wide)
4695 if (meta->idx_blob_wide)
4698 *p++ = 1; /* reserved */
4699 int64val = (guint64*)p;
4700 *int64val++ = GUINT64_TO_LE (valid_mask);
4701 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4703 int32val = (guint32*)p;
4704 for (i = 0; i < MONO_TABLE_NUM; i++){
4705 if (meta->tables [i].rows == 0)
4707 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4709 p = (unsigned char*)int32val;
4711 /* sort the tables that still need sorting */
4712 table = &assembly->tables [MONO_TABLE_CONSTANT];
4714 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4715 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4717 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4718 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4720 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4721 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4723 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4724 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4726 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4727 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4728 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4730 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4731 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4733 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4735 /* compress the tables */
4736 for (i = 0; i < MONO_TABLE_NUM; i++){
4739 guint32 bitfield = meta->tables [i].size_bitfield;
4740 if (!meta->tables [i].rows)
4742 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4743 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4744 meta->tables [i].base = (char*)p;
4745 for (row = 1; row <= meta->tables [i].rows; ++row) {
4746 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4747 for (col = 0; col < assembly->tables [i].columns; ++col) {
4748 switch (mono_metadata_table_size (bitfield, col)) {
4750 *p++ = values [col];
4753 *p++ = values [col] & 0xff;
4754 *p++ = (values [col] >> 8) & 0xff;
4757 *p++ = values [col] & 0xff;
4758 *p++ = (values [col] >> 8) & 0xff;
4759 *p++ = (values [col] >> 16) & 0xff;
4760 *p++ = (values [col] >> 24) & 0xff;
4763 g_assert_not_reached ();
4767 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4770 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4771 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4772 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4773 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4774 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4776 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4782 * Some tables in metadata need to be sorted according to some criteria, but
4783 * when methods and fields are first created with reflection, they may be assigned a token
4784 * that doesn't correspond to the final token they will get assigned after the sorting.
4785 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4786 * with the reflection objects that represent them. Once all the tables are set up, the
4787 * reflection objects will contains the correct table index. fixup_method() will fixup the
4788 * tokens for the method with ILGenerator @ilgen.
4791 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4793 guint32 code_idx = GPOINTER_TO_UINT (value);
4794 MonoReflectionILTokenInfo *iltoken;
4795 MonoReflectionFieldBuilder *field;
4796 MonoReflectionCtorBuilder *ctor;
4797 MonoReflectionMethodBuilder *method;
4798 MonoReflectionTypeBuilder *tb;
4799 MonoReflectionArrayMethod *am;
4801 unsigned char *target;
4803 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4804 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4805 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4806 switch (target [3]) {
4807 case MONO_TABLE_FIELD:
4808 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4809 field = (MonoReflectionFieldBuilder *)iltoken->member;
4810 idx = field->table_idx;
4811 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4812 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4813 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4815 g_assert_not_reached ();
4818 case MONO_TABLE_METHOD:
4819 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4820 method = (MonoReflectionMethodBuilder *)iltoken->member;
4821 idx = method->table_idx;
4822 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4823 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4824 idx = ctor->table_idx;
4825 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4826 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4827 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4828 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4830 g_assert_not_reached ();
4833 case MONO_TABLE_TYPEDEF:
4834 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4835 g_assert_not_reached ();
4836 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4837 idx = tb->table_idx;
4839 case MONO_TABLE_MEMBERREF:
4840 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4841 am = (MonoReflectionArrayMethod*)iltoken->member;
4842 idx = am->table_idx;
4843 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4844 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4845 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4846 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4847 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4848 g_assert (m->klass->generic_class || m->klass->generic_container);
4850 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4852 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4853 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4854 g_assert (is_field_on_inst (f));
4856 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4857 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4859 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4861 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4863 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4866 g_assert_not_reached ();
4869 case MONO_TABLE_METHODSPEC:
4870 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4871 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4872 g_assert (mono_method_signature (m)->generic_param_count);
4874 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4876 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4879 g_assert_not_reached ();
4883 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4885 target [0] = idx & 0xff;
4886 target [1] = (idx >> 8) & 0xff;
4887 target [2] = (idx >> 16) & 0xff;
4894 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4895 * value is not known when the table is emitted.
4898 fixup_cattrs (MonoDynamicImage *assembly)
4900 MonoDynamicTable *table;
4902 guint32 type, i, idx, token;
4905 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4907 for (i = 0; i < table->rows; ++i) {
4908 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4910 type = values [MONO_CUSTOM_ATTR_TYPE];
4911 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4912 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4913 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4914 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4917 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4918 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4919 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4920 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4921 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4922 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4923 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4924 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4931 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4933 MonoDynamicTable *table;
4936 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4938 alloc_table (table, table->rows);
4939 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4940 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4941 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4942 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4943 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4948 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4950 MonoDynamicTable *table;
4954 char *b = blob_size;
4956 guint32 idx, offset;
4958 if (rsrc->filename) {
4959 name = mono_string_to_utf8 (rsrc->filename);
4960 sname = g_path_get_basename (name);
4962 table = &assembly->tables [MONO_TABLE_FILE];
4964 alloc_table (table, table->rows);
4965 values = table->values + table->next_idx * MONO_FILE_SIZE;
4966 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4967 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4970 mono_sha1_get_digest_from_file (name, hash);
4971 mono_metadata_encode_value (20, b, &b);
4972 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4973 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4975 idx = table->next_idx++;
4977 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4983 data = mono_array_addr (rsrc->data, char, 0);
4984 len = mono_array_length (rsrc->data);
4990 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4991 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4992 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4993 mono_image_add_stream_data (&assembly->resources, data, len);
4997 * The entry should be emitted into the MANIFESTRESOURCE table of
4998 * the main module, but that needs to reference the FILE table
4999 * which isn't emitted yet.
5006 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5010 set_version_from_string (MonoString *version, guint32 *values)
5012 gchar *ver, *p, *str;
5015 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5016 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5017 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5018 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5021 ver = str = mono_string_to_utf8 (version);
5022 for (i = 0; i < 4; ++i) {
5023 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5029 /* handle Revision and Build */
5039 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5043 char *b = blob_size;
5048 len = mono_array_length (pkey);
5049 mono_metadata_encode_value (len, b, &b);
5050 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5051 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5053 assembly->public_key = (guint8 *)g_malloc (len);
5054 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5055 assembly->public_key_len = len;
5057 /* Special case: check for ECMA key (16 bytes) */
5058 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5059 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5060 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5061 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5062 /* minimum key size (in 2.0) is 384 bits */
5063 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5065 /* FIXME - verifier */
5066 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5067 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5069 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5075 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5078 MonoDynamicTable *table;
5079 MonoDynamicImage *assembly;
5080 MonoReflectionAssemblyBuilder *assemblyb;
5084 guint32 module_index;
5086 assemblyb = moduleb->assemblyb;
5087 assembly = moduleb->dynamic_image;
5088 domain = mono_object_domain (assemblyb);
5090 /* Emit ASSEMBLY table */
5091 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5092 alloc_table (table, 1);
5093 values = table->values + MONO_ASSEMBLY_SIZE;
5094 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5095 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5096 if (assemblyb->culture) {
5097 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5099 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5101 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5102 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5103 set_version_from_string (assemblyb->version, values);
5105 /* Emit FILE + EXPORTED_TYPE table */
5107 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5109 MonoReflectionModuleBuilder *file_module =
5110 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5111 if (file_module != moduleb) {
5112 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5114 if (file_module->types) {
5115 for (j = 0; j < file_module->num_types; ++j) {
5116 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5117 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, &error);
5118 mono_error_raise_exception (&error); /* FIXME don't raise here */
5123 if (assemblyb->loaded_modules) {
5124 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5125 MonoReflectionModule *file_module =
5126 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5127 mono_image_fill_file_table (domain, file_module, assembly);
5129 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5132 if (assemblyb->type_forwarders)
5133 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5135 /* Emit MANIFESTRESOURCE table */
5137 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5139 MonoReflectionModuleBuilder *file_module =
5140 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5141 /* The table for the main module is emitted later */
5142 if (file_module != moduleb) {
5144 if (file_module->resources) {
5145 int len = mono_array_length (file_module->resources);
5146 for (j = 0; j < len; ++j) {
5147 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5148 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5155 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5158 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5159 * for the modulebuilder @moduleb.
5160 * At the end of the process, method and field tokens are fixed up and the
5161 * on-disk compressed metadata representation is created.
5162 * Return TRUE on success, or FALSE on failure and sets @error
5165 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5167 MonoDynamicTable *table;
5168 MonoDynamicImage *assembly;
5169 MonoReflectionAssemblyBuilder *assemblyb;
5175 mono_error_init (error);
5177 assemblyb = moduleb->assemblyb;
5178 assembly = moduleb->dynamic_image;
5179 domain = mono_object_domain (assemblyb);
5181 if (assembly->text_rva)
5184 assembly->text_rva = START_TEXT_RVA;
5186 if (moduleb->is_main) {
5187 mono_image_emit_manifest (moduleb);
5190 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5191 table->rows = 1; /* .<Module> */
5193 alloc_table (table, table->rows);
5195 * Set the first entry.
5197 values = table->values + table->columns;
5198 values [MONO_TYPEDEF_FLAGS] = 0;
5199 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5200 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5201 values [MONO_TYPEDEF_EXTENDS] = 0;
5202 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5203 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5206 * handle global methods
5207 * FIXME: test what to do when global methods are defined in multiple modules.
5209 if (moduleb->global_methods) {
5210 table = &assembly->tables [MONO_TABLE_METHOD];
5211 table->rows += mono_array_length (moduleb->global_methods);
5212 alloc_table (table, table->rows);
5213 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5214 if (!mono_image_get_method_info (
5215 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5219 if (moduleb->global_fields) {
5220 table = &assembly->tables [MONO_TABLE_FIELD];
5221 table->rows += mono_array_length (moduleb->global_fields);
5222 alloc_table (table, table->rows);
5223 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5224 mono_image_get_field_info (
5225 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5232 table = &assembly->tables [MONO_TABLE_MODULE];
5233 alloc_table (table, 1);
5234 mono_image_fill_module_table (domain, moduleb, assembly);
5236 /* Collect all types into a list sorted by their table_idx */
5237 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5240 for (i = 0; i < moduleb->num_types; ++i) {
5241 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5242 collect_types (&types, type);
5245 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5246 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5247 table->rows += mono_ptr_array_size (types);
5248 alloc_table (table, table->rows);
5251 * Emit type names + namespaces at one place inside the string heap,
5252 * so load_class_names () needs to touch fewer pages.
5254 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5255 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5256 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5258 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5259 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5260 string_heap_insert_mstring (&assembly->sheap, tb->name);
5263 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5264 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5265 if (!mono_image_get_type_info (domain, type, assembly, error))
5270 * table->rows is already set above and in mono_image_fill_module_table.
5272 /* add all the custom attributes at the end, once all the indexes are stable */
5273 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5276 /* CAS assembly permissions */
5277 if (assemblyb->permissions_minimum)
5278 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5279 if (assemblyb->permissions_optional)
5280 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5281 if (assemblyb->permissions_refused)
5282 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5284 if (!module_add_cattrs (assembly, moduleb, error))
5288 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5290 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5291 * the final tokens and don't need another fixup pass. */
5293 if (moduleb->global_methods) {
5294 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5295 MonoReflectionMethodBuilder *mb = mono_array_get (
5296 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5297 if (!mono_image_add_methodimpl (assembly, mb, error))
5302 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5303 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5304 if (type->methods) {
5305 for (j = 0; j < type->num_methods; ++j) {
5306 MonoReflectionMethodBuilder *mb = mono_array_get (
5307 type->methods, MonoReflectionMethodBuilder*, j);
5309 if (!mono_image_add_methodimpl (assembly, mb, error))
5315 fixup_cattrs (assembly);
5318 mono_ptr_array_destroy (types);
5321 return mono_error_ok (error);
5324 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5327 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5329 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5332 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5336 guint32 import_lookup_table;
5340 guint32 import_address_table_rva;
5348 #ifndef DISABLE_REFLECTION_EMIT
5351 * mono_image_insert_string:
5352 * @module: module builder object
5355 * Insert @str into the user string stream of @module.
5358 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5360 MonoDynamicImage *assembly;
5365 if (!module->dynamic_image)
5366 mono_image_module_basic_init (module);
5368 assembly = module->dynamic_image;
5370 if (assembly->save) {
5371 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5372 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5373 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5375 char *swapped = g_malloc (2 * mono_string_length (str));
5376 const char *p = (const char*)mono_string_chars (str);
5378 swap_with_size (swapped, p, 2, mono_string_length (str));
5379 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5383 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5385 mono_image_add_stream_data (&assembly->us, "", 1);
5387 idx = assembly->us.index ++;
5390 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5392 return MONO_TOKEN_STRING | idx;
5396 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5400 MonoMethodSignature *sig;
5402 mono_error_init (error);
5404 klass = obj->vtable->klass;
5405 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5406 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5407 MonoMethodSignature *old;
5408 guint32 sig_token, parent;
5411 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5413 nargs = mono_array_length (opt_param_types);
5414 old = mono_method_signature (method);
5415 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5417 sig->hasthis = old->hasthis;
5418 sig->explicit_this = old->explicit_this;
5419 sig->call_convention = old->call_convention;
5420 sig->generic_param_count = old->generic_param_count;
5421 sig->param_count = old->param_count + nargs;
5422 sig->sentinelpos = old->param_count;
5423 sig->ret = old->ret;
5425 for (i = 0; i < old->param_count; i++)
5426 sig->params [i] = old->params [i];
5428 for (i = 0; i < nargs; i++) {
5429 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5430 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5431 if (!is_ok (error)) goto fail;
5434 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5435 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5436 parent >>= MONO_TYPEDEFORREF_BITS;
5438 parent <<= MONO_MEMBERREF_PARENT_BITS;
5439 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5441 sig_token = method_encode_signature (assembly, sig);
5442 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5443 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5444 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5445 ReflectionMethodBuilder rmb;
5446 guint32 parent, sig_token;
5447 int nopt_args, nparams, ngparams, i;
5449 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5452 rmb.opt_types = opt_param_types;
5453 nopt_args = mono_array_length (opt_param_types);
5455 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5456 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5457 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5459 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5460 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5461 sig->call_convention = rmb.call_conv;
5462 sig->generic_param_count = ngparams;
5463 sig->param_count = nparams + nopt_args;
5464 sig->sentinelpos = nparams;
5465 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5466 if (!is_ok (error)) goto fail;
5468 for (i = 0; i < nparams; i++) {
5469 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5470 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5471 if (!is_ok (error)) goto fail;
5474 for (i = 0; i < nopt_args; i++) {
5475 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5476 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5477 if (!is_ok (error)) goto fail;
5480 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5484 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5485 if (!mono_error_ok (error))
5487 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5489 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5490 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5492 char *name = mono_string_to_utf8 (rmb.name);
5493 token = mono_image_get_varargs_method_token (
5494 assembly, parent, name, sig_token);
5497 g_error ("requested method token for %s\n", klass->name);
5500 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5501 register_dyn_token (assembly, token, obj);
5504 g_assert (!mono_error_ok (error));
5509 * mono_image_create_token:
5510 * @assembly: a dynamic assembly
5512 * @register_token: Whenever to register the token in the assembly->tokens hash.
5514 * Get a token to insert in the IL code stream for the given MemberInfo.
5515 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5516 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5520 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5521 gboolean create_open_instance, gboolean register_token,
5527 mono_error_init (error);
5529 klass = obj->vtable->klass;
5531 /* Check for user defined reflection objects */
5532 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5533 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5534 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5538 if (strcmp (klass->name, "MethodBuilder") == 0) {
5539 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5540 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5542 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5543 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5545 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5546 if (!mono_error_ok (error))
5549 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5550 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5551 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5552 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5554 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5555 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5557 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5558 if (!mono_error_ok (error))
5561 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5562 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5563 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5564 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5565 if (tb->generic_params) {
5566 token = mono_image_get_generic_field_token (assembly, fb, error);
5567 return_val_if_nok (error, 0);
5569 if (tb->module->dynamic_image == assembly) {
5570 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5572 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5575 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5576 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5577 if (create_open_instance && tb->generic_params) {
5579 init_type_builder_generics (obj);
5580 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5581 return_val_if_nok (error, 0);
5582 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5583 token = mono_metadata_token_from_dor (token);
5584 } else if (tb->module->dynamic_image == assembly) {
5585 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5588 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5589 return_val_if_nok (error, 0);
5590 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5592 } else if (strcmp (klass->name, "MonoType") == 0) {
5593 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594 return_val_if_nok (error, 0);
5595 MonoClass *mc = mono_class_from_mono_type (type);
5596 token = mono_metadata_token_from_dor (
5597 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5598 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5599 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5600 return_val_if_nok (error, 0);
5601 token = mono_metadata_token_from_dor (
5602 mono_image_typedef_or_ref (assembly, type));
5603 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5604 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5605 return_val_if_nok (error, 0);
5606 token = mono_metadata_token_from_dor (
5607 mono_image_typedef_or_ref (assembly, type));
5608 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5609 strcmp (klass->name, "MonoMethod") == 0 ||
5610 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5611 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5612 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5613 if (m->method->is_inflated) {
5614 if (create_open_instance)
5615 token = mono_image_get_methodspec_token (assembly, m->method);
5617 token = mono_image_get_inflated_method_token (assembly, m->method);
5618 } else if ((m->method->klass->image == &assembly->image) &&
5619 !m->method->klass->generic_class) {
5620 static guint32 method_table_idx = 0xffffff;
5621 if (m->method->klass->wastypebuilder) {
5622 /* we use the same token as the one that was assigned
5623 * to the Methodbuilder.
5624 * FIXME: do the equivalent for Fields.
5626 token = m->method->token;
5629 * Each token should have a unique index, but the indexes are
5630 * assigned by managed code, so we don't know about them. An
5631 * easy solution is to count backwards...
5633 method_table_idx --;
5634 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5637 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5639 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5640 } else if (strcmp (klass->name, "MonoField") == 0) {
5641 MonoReflectionField *f = (MonoReflectionField *)obj;
5642 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5643 static guint32 field_table_idx = 0xffffff;
5645 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5647 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5649 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5650 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5651 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5652 token = mono_image_get_array_token (assembly, m, error);
5653 return_val_if_nok (error, 0);
5654 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5655 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5656 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5657 return_val_if_nok (error, 0);
5658 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5659 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5660 return_val_if_nok (error, 0);
5661 token = mono_metadata_token_from_dor (
5662 mono_image_typedef_or_ref (assembly, type));
5663 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5664 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5665 token = mono_image_get_field_on_inst_token (assembly, f, error);
5666 return_val_if_nok (error, 0);
5667 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5668 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5669 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5670 if (!mono_error_ok (error))
5672 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5673 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5674 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5675 if (!mono_error_ok (error))
5677 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5678 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5679 return_val_if_nok (error, 0);
5680 token = mono_metadata_token_from_dor (
5681 mono_image_typedef_or_ref (assembly, type));
5683 g_error ("requested token for %s\n", klass->name);
5687 mono_image_register_token (assembly, token, obj);
5693 * mono_image_register_token:
5695 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5696 * the Module.ResolveXXXToken () methods to work.
5699 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5703 dynamic_image_lock (assembly);
5704 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5706 /* There could be multiple MethodInfo objects with the same token */
5707 //g_assert (prev == obj);
5709 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5711 dynamic_image_unlock (assembly);
5714 static MonoDynamicImage*
5715 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5717 static const guchar entrycode [16] = {0xff, 0x25, 0};
5718 MonoDynamicImage *image;
5721 const char *version;
5723 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5724 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5726 version = mono_get_runtime_info ()->runtime_version;
5729 /* The MonoGHashTable's need GC tracking */
5730 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5732 image = g_new0 (MonoDynamicImage, 1);
5735 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5737 /*g_print ("created image %p\n", image);*/
5738 /* keep in sync with image.c */
5739 image->image.name = assembly_name;
5740 image->image.assembly_name = image->image.name; /* they may be different */
5741 image->image.module_name = module_name;
5742 image->image.version = g_strdup (version);
5743 image->image.md_version_major = 1;
5744 image->image.md_version_minor = 1;
5745 image->image.dynamic = TRUE;
5747 image->image.references = g_new0 (MonoAssembly*, 1);
5748 image->image.references [0] = NULL;
5750 mono_image_init (&image->image);
5752 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");
5753 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5754 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5755 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5756 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5757 image->handleref = g_hash_table_new (NULL, NULL);
5758 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");
5759 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5760 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");
5761 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");
5762 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5763 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5764 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5765 image->gen_params = g_ptr_array_new ();
5766 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5768 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5769 string_heap_init (&image->sheap);
5770 mono_image_add_stream_data (&image->us, "", 1);
5771 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5772 /* import tables... */
5773 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5774 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5775 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5776 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5777 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5778 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5779 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5780 stream_data_align (&image->code);
5782 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5784 for (i=0; i < MONO_TABLE_NUM; ++i) {
5785 image->tables [i].next_idx = 1;
5786 image->tables [i].columns = table_sizes [i];
5789 image->image.assembly = (MonoAssembly*)assembly;
5790 image->run = assembly->run;
5791 image->save = assembly->save;
5792 image->pe_kind = 0x1; /* ILOnly */
5793 image->machine = 0x14c; /* I386 */
5795 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5797 dynamic_images_lock ();
5799 if (!dynamic_images)
5800 dynamic_images = g_ptr_array_new ();
5802 g_ptr_array_add (dynamic_images, image);
5804 dynamic_images_unlock ();
5811 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5817 release_hashtable (MonoGHashTable **hash)
5820 mono_g_hash_table_destroy (*hash);
5826 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5828 release_hashtable (&image->token_fixups);
5829 release_hashtable (&image->handleref_managed);
5830 release_hashtable (&image->tokens);
5831 release_hashtable (&image->remapped_tokens);
5832 release_hashtable (&image->generic_def_objects);
5833 release_hashtable (&image->methodspec);
5836 // Free dynamic image pass one: Free resources but not image itself
5838 mono_dynamic_image_free (MonoDynamicImage *image)
5840 MonoDynamicImage *di = image;
5845 mono_g_hash_table_destroy (di->methodspec);
5847 g_hash_table_destroy (di->typespec);
5849 g_hash_table_destroy (di->typeref);
5851 g_hash_table_destroy (di->handleref);
5852 if (di->handleref_managed)
5853 mono_g_hash_table_destroy (di->handleref_managed);
5855 mono_g_hash_table_destroy (di->tokens);
5856 if (di->remapped_tokens)
5857 mono_g_hash_table_destroy (di->remapped_tokens);
5858 if (di->generic_def_objects)
5859 mono_g_hash_table_destroy (di->generic_def_objects);
5860 if (di->blob_cache) {
5861 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5862 g_hash_table_destroy (di->blob_cache);
5864 if (di->standalonesig_cache)
5865 g_hash_table_destroy (di->standalonesig_cache);
5866 for (list = di->array_methods; list; list = list->next) {
5867 ArrayMethod *am = (ArrayMethod *)list->data;
5872 g_list_free (di->array_methods);
5873 if (di->gen_params) {
5874 for (i = 0; i < di->gen_params->len; i++) {
5875 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5876 mono_gc_deregister_root ((char*) &entry->gparam);
5879 g_ptr_array_free (di->gen_params, TRUE);
5881 if (di->token_fixups)
5882 mono_g_hash_table_destroy (di->token_fixups);
5883 if (di->method_to_table_idx)
5884 g_hash_table_destroy (di->method_to_table_idx);
5885 if (di->field_to_table_idx)
5886 g_hash_table_destroy (di->field_to_table_idx);
5887 if (di->method_aux_hash)
5888 g_hash_table_destroy (di->method_aux_hash);
5889 if (di->vararg_aux_hash)
5890 g_hash_table_destroy (di->vararg_aux_hash);
5891 g_free (di->strong_name);
5892 g_free (di->win32_res);
5894 g_free (di->public_key);
5896 /*g_print ("string heap destroy for image %p\n", di);*/
5897 mono_dynamic_stream_reset (&di->sheap);
5898 mono_dynamic_stream_reset (&di->code);
5899 mono_dynamic_stream_reset (&di->resources);
5900 mono_dynamic_stream_reset (&di->us);
5901 mono_dynamic_stream_reset (&di->blob);
5902 mono_dynamic_stream_reset (&di->tstream);
5903 mono_dynamic_stream_reset (&di->guid);
5904 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5905 g_free (di->tables [i].values);
5908 dynamic_images_lock ();
5911 g_ptr_array_remove (dynamic_images, di);
5913 dynamic_images_unlock ();
5916 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5918 mono_dynamic_image_free_image (MonoDynamicImage *image)
5920 /* See create_dynamic_mono_image () */
5922 /* Allocated using GC_MALLOC */
5928 #ifndef DISABLE_REFLECTION_EMIT
5931 * mono_image_basic_init:
5932 * @assembly: an assembly builder object
5934 * Create the MonoImage that represents the assembly builder and setup some
5935 * of the helper hash table and the basic metadata streams.
5938 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5940 MonoDynamicAssembly *assembly;
5941 MonoDynamicImage *image;
5942 MonoDomain *domain = mono_object_domain (assemblyb);
5944 if (assemblyb->dynamic_assembly)
5948 /* assembly->assembly.image might be GC allocated */
5949 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5951 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5954 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5956 assembly->assembly.ref_count = 1;
5957 assembly->assembly.dynamic = TRUE;
5958 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5959 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5960 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5961 if (assemblyb->culture)
5962 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5964 assembly->assembly.aname.culture = g_strdup ("");
5966 if (assemblyb->version) {
5967 char *vstr = mono_string_to_utf8 (assemblyb->version);
5968 char **version = g_strsplit (vstr, ".", 4);
5969 char **parts = version;
5970 assembly->assembly.aname.major = atoi (*parts++);
5971 assembly->assembly.aname.minor = atoi (*parts++);
5972 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5973 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5975 g_strfreev (version);
5978 assembly->assembly.aname.major = 0;
5979 assembly->assembly.aname.minor = 0;
5980 assembly->assembly.aname.build = 0;
5981 assembly->assembly.aname.revision = 0;
5984 assembly->run = assemblyb->access != 2;
5985 assembly->save = assemblyb->access != 1;
5986 assembly->domain = domain;
5988 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5989 image->initial_image = TRUE;
5990 assembly->assembly.aname.name = image->image.name;
5991 assembly->assembly.image = &image->image;
5992 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5993 /* -1 to correct for the trailing NULL byte */
5994 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5995 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5997 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6000 mono_domain_assemblies_lock (domain);
6001 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6002 mono_domain_assemblies_unlock (domain);
6004 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6006 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6008 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6011 #endif /* !DISABLE_REFLECTION_EMIT */
6013 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6016 calc_section_size (MonoDynamicImage *assembly)
6020 /* alignment constraints */
6021 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6022 g_assert ((assembly->code.index % 4) == 0);
6023 assembly->meta_size += 3;
6024 assembly->meta_size &= ~3;
6025 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6026 g_assert ((assembly->resources.index % 4) == 0);
6028 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6029 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6032 if (assembly->win32_res) {
6033 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6035 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6036 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6040 assembly->sections [MONO_SECTION_RELOC].size = 12;
6041 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6051 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6055 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6057 ResTreeNode *t1 = (ResTreeNode*)a;
6058 ResTreeNode *t2 = (ResTreeNode*)b;
6060 return t1->id - t2->id;
6064 * resource_tree_create:
6066 * Organize the resources into a resource tree.
6068 static ResTreeNode *
6069 resource_tree_create (MonoArray *win32_resources)
6071 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6075 tree = g_new0 (ResTreeNode, 1);
6077 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6078 MonoReflectionWin32Resource *win32_res =
6079 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6083 /* FIXME: BUG: this stores managed references in unmanaged memory */
6084 lang_node = g_new0 (ResTreeNode, 1);
6085 lang_node->id = win32_res->lang_id;
6086 lang_node->win32_res = win32_res;
6088 /* Create type node if neccesary */
6090 for (l = tree->children; l; l = l->next)
6091 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6092 type_node = (ResTreeNode*)l->data;
6097 type_node = g_new0 (ResTreeNode, 1);
6098 type_node->id = win32_res->res_type;
6101 * The resource types have to be sorted otherwise
6102 * Windows Explorer can't display the version information.
6104 tree->children = g_slist_insert_sorted (tree->children,
6105 type_node, resource_tree_compare_by_id);
6108 /* Create res node if neccesary */
6110 for (l = type_node->children; l; l = l->next)
6111 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6112 res_node = (ResTreeNode*)l->data;
6117 res_node = g_new0 (ResTreeNode, 1);
6118 res_node->id = win32_res->res_id;
6119 type_node->children = g_slist_append (type_node->children, res_node);
6122 res_node->children = g_slist_append (res_node->children, lang_node);
6129 * resource_tree_encode:
6131 * Encode the resource tree into the format used in the PE file.
6134 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6137 MonoPEResourceDir dir;
6138 MonoPEResourceDirEntry dir_entry;
6139 MonoPEResourceDataEntry data_entry;
6141 guint32 res_id_entries;
6144 * For the format of the resource directory, see the article
6145 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6149 memset (&dir, 0, sizeof (dir));
6150 memset (&dir_entry, 0, sizeof (dir_entry));
6151 memset (&data_entry, 0, sizeof (data_entry));
6153 g_assert (sizeof (dir) == 16);
6154 g_assert (sizeof (dir_entry) == 8);
6155 g_assert (sizeof (data_entry) == 16);
6157 node->offset = p - begin;
6159 /* IMAGE_RESOURCE_DIRECTORY */
6160 res_id_entries = g_slist_length (node->children);
6161 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6163 memcpy (p, &dir, sizeof (dir));
6166 /* Reserve space for entries */
6168 p += sizeof (dir_entry) * res_id_entries;
6170 /* Write children */
6171 for (l = node->children; l; l = l->next) {
6172 ResTreeNode *child = (ResTreeNode*)l->data;
6174 if (child->win32_res) {
6177 child->offset = p - begin;
6179 /* IMAGE_RESOURCE_DATA_ENTRY */
6180 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6181 size = mono_array_length (child->win32_res->res_data);
6182 data_entry.rde_size = GUINT32_TO_LE (size);
6184 memcpy (p, &data_entry, sizeof (data_entry));
6185 p += sizeof (data_entry);
6187 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6190 resource_tree_encode (child, begin, p, &p);
6194 /* IMAGE_RESOURCE_ENTRY */
6195 for (l = node->children; l; l = l->next) {
6196 ResTreeNode *child = (ResTreeNode*)l->data;
6198 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6199 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6201 memcpy (entries, &dir_entry, sizeof (dir_entry));
6202 entries += sizeof (dir_entry);
6209 resource_tree_free (ResTreeNode * node)
6212 for (list = node->children; list; list = list->next)
6213 resource_tree_free ((ResTreeNode*)list->data);
6214 g_slist_free(node->children);
6219 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6224 MonoReflectionWin32Resource *win32_res;
6227 if (!assemblyb->win32_resources)
6231 * Resources are stored in a three level tree inside the PE file.
6232 * - level one contains a node for each type of resource
6233 * - level two contains a node for each resource
6234 * - level three contains a node for each instance of a resource for a
6235 * specific language.
6238 tree = resource_tree_create (assemblyb->win32_resources);
6240 /* Estimate the size of the encoded tree */
6242 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6243 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6244 size += mono_array_length (win32_res->res_data);
6246 /* Directory structure */
6247 size += mono_array_length (assemblyb->win32_resources) * 256;
6248 p = buf = (char *)g_malloc (size);
6250 resource_tree_encode (tree, p, p, &p);
6252 g_assert (p - buf <= size);
6254 assembly->win32_res = (char *)g_malloc (p - buf);
6255 assembly->win32_res_size = p - buf;
6256 memcpy (assembly->win32_res, buf, p - buf);
6259 resource_tree_free (tree);
6263 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6265 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6268 p += sizeof (MonoPEResourceDir);
6269 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6270 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6271 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6272 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6273 fixup_resource_directory (res_section, child, rva);
6275 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6276 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6279 p += sizeof (MonoPEResourceDirEntry);
6284 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6287 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6288 g_error ("WriteFile returned %d\n", GetLastError ());
6292 * mono_image_create_pefile:
6293 * @mb: a module builder object
6295 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6296 * assembly->pefile where it can be easily retrieved later in chunks.
6299 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6301 MonoMSDOSHeader *msdos;
6302 MonoDotNetHeader *header;
6303 MonoSectionTable *section;
6304 MonoCLIHeader *cli_header;
6305 guint32 size, image_size, virtual_base, text_offset;
6306 guint32 header_start, section_start, file_offset, virtual_offset;
6307 MonoDynamicImage *assembly;
6308 MonoReflectionAssemblyBuilder *assemblyb;
6309 MonoDynamicStream pefile_stream = {0};
6310 MonoDynamicStream *pefile = &pefile_stream;
6312 guint32 *rva, value;
6314 static const unsigned char msheader[] = {
6315 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6316 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6319 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6320 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6321 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6322 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6325 mono_error_init (error);
6327 assemblyb = mb->assemblyb;
6329 mono_image_basic_init (assemblyb);
6330 assembly = mb->dynamic_image;
6332 assembly->pe_kind = assemblyb->pe_kind;
6333 assembly->machine = assemblyb->machine;
6334 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6335 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6337 if (!mono_image_build_metadata (mb, error))
6341 if (mb->is_main && assemblyb->resources) {
6342 int len = mono_array_length (assemblyb->resources);
6343 for (i = 0; i < len; ++i)
6344 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6347 if (mb->resources) {
6348 int len = mono_array_length (mb->resources);
6349 for (i = 0; i < len; ++i)
6350 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6353 if (!build_compressed_metadata (assembly, error))
6357 assembly_add_win32_resources (assembly, assemblyb);
6359 nsections = calc_section_size (assembly);
6361 /* The DOS header and stub */
6362 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6363 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6365 /* the dotnet header */
6366 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6368 /* the section tables */
6369 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6371 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6372 virtual_offset = VIRT_ALIGN;
6375 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6376 if (!assembly->sections [i].size)
6379 file_offset += FILE_ALIGN - 1;
6380 file_offset &= ~(FILE_ALIGN - 1);
6381 virtual_offset += VIRT_ALIGN - 1;
6382 virtual_offset &= ~(VIRT_ALIGN - 1);
6384 assembly->sections [i].offset = file_offset;
6385 assembly->sections [i].rva = virtual_offset;
6387 file_offset += assembly->sections [i].size;
6388 virtual_offset += assembly->sections [i].size;
6389 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6392 file_offset += FILE_ALIGN - 1;
6393 file_offset &= ~(FILE_ALIGN - 1);
6395 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6397 /* back-patch info */
6398 msdos = (MonoMSDOSHeader*)pefile->data;
6399 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6401 header = (MonoDotNetHeader*)(pefile->data + header_start);
6402 header->pesig [0] = 'P';
6403 header->pesig [1] = 'E';
6405 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6406 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6407 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6408 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6409 if (assemblyb->pekind == 1) {
6411 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6414 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6417 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6419 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6420 header->pe.pe_major = 6;
6421 header->pe.pe_minor = 0;
6422 size = assembly->sections [MONO_SECTION_TEXT].size;
6423 size += FILE_ALIGN - 1;
6424 size &= ~(FILE_ALIGN - 1);
6425 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6426 size = assembly->sections [MONO_SECTION_RSRC].size;
6427 size += FILE_ALIGN - 1;
6428 size &= ~(FILE_ALIGN - 1);
6429 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6430 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6431 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6432 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6433 /* pe_rva_entry_point always at the beginning of the text section */
6434 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6436 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6437 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6438 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6439 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6440 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6441 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6442 size = section_start;
6443 size += FILE_ALIGN - 1;
6444 size &= ~(FILE_ALIGN - 1);
6445 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6447 size += VIRT_ALIGN - 1;
6448 size &= ~(VIRT_ALIGN - 1);
6449 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6452 // Translate the PEFileKind value to the value expected by the Windows loader
6458 // PEFileKinds.Dll == 1
6459 // PEFileKinds.ConsoleApplication == 2
6460 // PEFileKinds.WindowApplication == 3
6463 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6464 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6466 if (assemblyb->pekind == 3)
6471 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6473 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6474 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6475 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6476 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6477 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6478 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6480 /* fill data directory entries */
6482 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6483 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6485 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6486 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6488 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6489 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6490 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6491 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6492 /* patch entrypoint name */
6493 if (assemblyb->pekind == 1)
6494 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6496 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6497 /* patch imported function RVA name */
6498 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6499 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6501 /* the import table */
6502 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6503 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6504 /* patch imported dll RVA name and other entries in the dir */
6505 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6506 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6507 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6508 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6509 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6510 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6512 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6513 value = (assembly->text_rva + assembly->imp_names_offset);
6514 *p++ = (value) & 0xff;
6515 *p++ = (value >> 8) & (0xff);
6516 *p++ = (value >> 16) & (0xff);
6517 *p++ = (value >> 24) & (0xff);
6519 /* the CLI header info */
6520 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6521 cli_header->ch_size = GUINT32_FROM_LE (72);
6522 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6523 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6524 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6525 if (assemblyb->entry_point) {
6526 guint32 table_idx = 0;
6527 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6528 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6529 table_idx = methodb->table_idx;
6531 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6533 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6535 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6537 /* The embedded managed resources */
6538 text_offset = assembly->text_rva + assembly->code.index;
6539 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6540 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6541 text_offset += assembly->resources.index;
6542 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6543 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6544 text_offset += assembly->meta_size;
6545 if (assembly->strong_name_size) {
6546 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6547 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6548 text_offset += assembly->strong_name_size;
6551 /* write the section tables and section content */
6552 section = (MonoSectionTable*)(pefile->data + section_start);
6553 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6554 static const char section_names [][7] = {
6555 ".text", ".rsrc", ".reloc"
6557 if (!assembly->sections [i].size)
6559 strcpy (section->st_name, section_names [i]);
6560 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6561 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6562 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6563 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6564 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6565 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6566 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6570 checked_write_file (file, pefile->data, pefile->index);
6572 mono_dynamic_stream_reset (pefile);
6574 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6575 if (!assembly->sections [i].size)
6578 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6579 g_error ("SetFilePointer returned %d\n", GetLastError ());
6582 case MONO_SECTION_TEXT:
6583 /* patch entry point */
6584 p = (guchar*)(assembly->code.data + 2);
6585 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6586 *p++ = (value) & 0xff;
6587 *p++ = (value >> 8) & 0xff;
6588 *p++ = (value >> 16) & 0xff;
6589 *p++ = (value >> 24) & 0xff;
6591 checked_write_file (file, assembly->code.data, assembly->code.index);
6592 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6593 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6594 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6597 g_free (assembly->image.raw_metadata);
6599 case MONO_SECTION_RELOC: {
6603 guint16 type_and_offset;
6607 g_assert (sizeof (reloc) == 12);
6609 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6610 reloc.block_size = GUINT32_FROM_LE (12);
6613 * the entrypoint is always at the start of the text section
6614 * 3 is IMAGE_REL_BASED_HIGHLOW
6615 * 2 is patch_size_rva - text_rva
6617 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6620 checked_write_file (file, &reloc, sizeof (reloc));
6624 case MONO_SECTION_RSRC:
6625 if (assembly->win32_res) {
6627 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6628 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6629 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6633 g_assert_not_reached ();
6637 /* check that the file is properly padded */
6638 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6639 g_error ("SetFilePointer returned %d\n", GetLastError ());
6640 if (! SetEndOfFile (file))
6641 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6643 mono_dynamic_stream_reset (&assembly->code);
6644 mono_dynamic_stream_reset (&assembly->us);
6645 mono_dynamic_stream_reset (&assembly->blob);
6646 mono_dynamic_stream_reset (&assembly->guid);
6647 mono_dynamic_stream_reset (&assembly->sheap);
6649 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6650 g_hash_table_destroy (assembly->blob_cache);
6651 assembly->blob_cache = NULL;
6656 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6659 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6661 g_assert_not_reached ();
6664 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6666 #ifndef DISABLE_REFLECTION_EMIT
6668 MonoReflectionModule *
6669 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6672 MonoReflectionModule *result = NULL;
6675 MonoImageOpenStatus status;
6676 MonoDynamicAssembly *assembly;
6677 guint32 module_count;
6678 MonoImage **new_modules;
6679 gboolean *new_modules_loaded;
6681 name = mono_string_to_utf8 (fileName);
6683 image = mono_image_open (name, &status);
6686 if (status == MONO_IMAGE_ERROR_ERRNO)
6687 exc = mono_get_exception_file_not_found (fileName);
6689 exc = mono_get_exception_bad_image_format (name);
6691 mono_raise_exception (exc);
6696 assembly = ab->dynamic_assembly;
6697 image->assembly = (MonoAssembly*)assembly;
6699 module_count = image->assembly->image->module_count;
6700 new_modules = g_new0 (MonoImage *, module_count + 1);
6701 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6703 if (image->assembly->image->modules)
6704 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6705 if (image->assembly->image->modules_loaded)
6706 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6707 new_modules [module_count] = image;
6708 new_modules_loaded [module_count] = TRUE;
6709 mono_image_addref (image);
6711 g_free (image->assembly->image->modules);
6712 image->assembly->image->modules = new_modules;
6713 image->assembly->image->modules_loaded = new_modules_loaded;
6714 image->assembly->image->module_count ++;
6716 mono_assembly_load_references (image, &status);
6718 mono_image_close (image);
6719 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6722 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6723 mono_error_raise_exception (&error); /* FIXME don't raise here */
6727 #endif /* DISABLE_REFLECTION_EMIT */
6730 * We need to return always the same object for MethodInfo, FieldInfo etc..
6731 * but we need to consider the reflected type.
6732 * type uses a different hash, since it uses custom hash/equal functions.
6737 MonoClass *refclass;
6741 reflected_equal (gconstpointer a, gconstpointer b) {
6742 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6743 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6745 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6749 reflected_hash (gconstpointer a) {
6750 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6751 return mono_aligned_addr_hash (ea->item);
6754 #define CHECK_OBJECT(t,p,k) \
6760 mono_domain_lock (domain); \
6761 if (!domain->refobject_hash) \
6762 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"); \
6763 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6764 mono_domain_unlock (domain); \
6767 mono_domain_unlock (domain); \
6770 #ifdef HAVE_BOEHM_GC
6771 /* ReflectedEntry doesn't need to be GC tracked */
6772 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6773 #define FREE_REFENTRY(entry) g_free ((entry))
6774 #define REFENTRY_REQUIRES_CLEANUP
6776 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6778 #define FREE_REFENTRY(entry)
6781 #define CACHE_OBJECT(t,p,o,k) \
6784 ReflectedEntry pe; \
6786 pe.refclass = (k); \
6787 mono_domain_lock (domain); \
6788 if (!domain->refobject_hash) \
6789 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"); \
6790 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6792 ReflectedEntry *e = ALLOC_REFENTRY; \
6794 e->refclass = (k); \
6795 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6798 mono_domain_unlock (domain); \
6803 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6805 mono_domain_lock (domain);
6806 if (domain->refobject_hash) {
6808 gpointer orig_pe, orig_value;
6811 pe.refclass = klass;
6812 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6813 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6814 FREE_REFENTRY (orig_pe);
6817 mono_domain_unlock (domain);
6820 #ifdef REFENTRY_REQUIRES_CLEANUP
6822 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6824 FREE_REFENTRY (key);
6829 mono_reflection_cleanup_domain (MonoDomain *domain)
6831 if (domain->refobject_hash) {
6832 /*let's avoid scanning the whole hashtable if not needed*/
6833 #ifdef REFENTRY_REQUIRES_CLEANUP
6834 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6836 mono_g_hash_table_destroy (domain->refobject_hash);
6837 domain->refobject_hash = NULL;
6841 #ifndef DISABLE_REFLECTION_EMIT
6843 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6845 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6849 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6851 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6855 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6857 MonoDynamicImage *image = moduleb->dynamic_image;
6858 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6862 MonoImage **new_modules;
6864 char *name, *fqname;
6866 * FIXME: we already created an image in mono_image_basic_init (), but
6867 * we don't know which module it belongs to, since that is only
6868 * determined at assembly save time.
6870 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6871 name = mono_string_to_utf8 (ab->name);
6872 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6873 if (!mono_error_ok (&error)) {
6875 mono_error_raise_exception (&error);
6877 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6879 moduleb->module.image = &image->image;
6880 moduleb->dynamic_image = image;
6881 register_module (mono_object_domain (moduleb), moduleb, image);
6883 /* register the module with the assembly */
6884 ass = ab->dynamic_assembly->assembly.image;
6885 module_count = ass->module_count;
6886 new_modules = g_new0 (MonoImage *, module_count + 1);
6889 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6890 new_modules [module_count] = &image->image;
6891 mono_image_addref (&image->image);
6893 g_free (ass->modules);
6894 ass->modules = new_modules;
6895 ass->module_count ++;
6900 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6902 MonoDynamicImage *image = moduleb->dynamic_image;
6904 g_assert (type->type);
6905 image->wrappers_type = mono_class_from_mono_type (type->type);
6911 * mono_assembly_get_object:
6912 * @domain: an app domain
6913 * @assembly: an assembly
6915 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6917 MonoReflectionAssembly*
6918 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6921 MonoReflectionAssembly *result;
6922 result = mono_assembly_get_object_checked (domain, assembly, &error);
6923 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6927 * mono_assembly_get_object_checked:
6928 * @domain: an app domain
6929 * @assembly: an assembly
6931 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6933 MonoReflectionAssembly*
6934 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6936 MonoReflectionAssembly *res;
6938 mono_error_init (error);
6940 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6941 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6944 res->assembly = assembly;
6946 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6951 MonoReflectionModule*
6952 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6955 MonoReflectionModule *result;
6956 result = mono_module_get_object_checked (domain, image, &error);
6957 mono_error_raise_exception (&error);
6961 MonoReflectionModule*
6962 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6964 MonoReflectionModule *res;
6967 mono_error_init (error);
6968 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6969 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6974 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6977 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6979 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6980 basename = g_path_get_basename (image->name);
6981 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6982 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6986 if (image->assembly->image == image) {
6987 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6991 if (image->assembly->image->modules) {
6992 for (i = 0; i < image->assembly->image->module_count; i++) {
6993 if (image->assembly->image->modules [i] == image)
6994 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6996 g_assert (res->token);
7000 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7003 MonoReflectionModule*
7004 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7007 MonoReflectionModule *result;
7008 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7009 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7013 MonoReflectionModule*
7014 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7016 MonoReflectionModule *res;
7017 MonoTableInfo *table;
7018 guint32 cols [MONO_FILE_SIZE];
7020 guint32 i, name_idx;
7023 mono_error_init (error);
7025 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7029 table = &image->tables [MONO_TABLE_FILE];
7030 g_assert (table_index < table->rows);
7031 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7034 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7037 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7038 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7040 /* Check whenever the row has a corresponding row in the moduleref table */
7041 table = &image->tables [MONO_TABLE_MODULEREF];
7042 for (i = 0; i < table->rows; ++i) {
7043 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7044 val = mono_metadata_string_heap (image, name_idx);
7045 if (strcmp (val, name) == 0)
7046 res->image = image->modules [i];
7049 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7050 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7051 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7052 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7053 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7059 verify_safe_for_managed_space (MonoType *type)
7061 switch (type->type) {
7063 case MONO_TYPE_ARRAY:
7064 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7066 return verify_safe_for_managed_space (type->data.type);
7067 case MONO_TYPE_SZARRAY:
7068 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7069 case MONO_TYPE_GENERICINST: {
7070 MonoGenericInst *inst = type->data.generic_class->inst;
7074 for (i = 0; i < inst->type_argc; ++i)
7075 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7081 case MONO_TYPE_MVAR:
7089 mono_type_normalize (MonoType *type)
7092 MonoGenericClass *gclass;
7093 MonoGenericInst *ginst;
7095 MonoGenericContainer *gcontainer;
7096 MonoType **argv = NULL;
7097 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7099 if (type->type != MONO_TYPE_GENERICINST)
7102 gclass = type->data.generic_class;
7103 ginst = gclass->context.class_inst;
7104 if (!ginst->is_open)
7107 gtd = gclass->container_class;
7108 gcontainer = gtd->generic_container;
7109 argv = g_newa (MonoType*, ginst->type_argc);
7111 for (i = 0; i < ginst->type_argc; ++i) {
7112 MonoType *t = ginst->type_argv [i], *norm;
7113 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7114 is_denorm_gtd = FALSE;
7115 norm = mono_type_normalize (t);
7118 requires_rebind = TRUE;
7122 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7124 if (requires_rebind) {
7125 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7126 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7132 * mono_type_get_object:
7133 * @domain: an app domain
7136 * Return an System.MonoType object representing the type @type.
7139 mono_type_get_object (MonoDomain *domain, MonoType *type)
7142 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7143 mono_error_raise_exception (&error);
7149 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7151 MonoType *norm_type;
7152 MonoReflectionType *res;
7155 mono_error_init (error);
7157 klass = mono_class_from_mono_type (type);
7159 /*we must avoid using @type as it might have come
7160 * from a mono_metadata_type_dup and the caller
7161 * expects that is can be freed.
7162 * Using the right type from
7164 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7166 /* void is very common */
7167 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7168 return (MonoReflectionType*)domain->typeof_void;
7171 * If the vtable of the given class was already created, we can use
7172 * the MonoType from there and avoid all locking and hash table lookups.
7174 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7175 * that the resulting object is different.
7177 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7178 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7179 if (vtable && vtable->type)
7180 return (MonoReflectionType *)vtable->type;
7183 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7184 mono_domain_lock (domain);
7185 if (!domain->type_hash)
7186 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7187 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7188 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7189 mono_domain_unlock (domain);
7190 mono_loader_unlock ();
7194 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7195 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7196 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7197 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7198 * artifact of how generics are encoded and should be transparent to managed code so we
7199 * need to weed out this diference when retrieving managed System.Type objects.
7201 norm_type = mono_type_normalize (type);
7202 if (norm_type != type) {
7203 res = mono_type_get_object_checked (domain, norm_type, error);
7204 if (!mono_error_ok (error))
7206 mono_g_hash_table_insert (domain->type_hash, type, res);
7207 mono_domain_unlock (domain);
7208 mono_loader_unlock ();
7212 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7213 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7216 if (!verify_safe_for_managed_space (type)) {
7217 mono_domain_unlock (domain);
7218 mono_loader_unlock ();
7219 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7223 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7224 gboolean is_type_done = TRUE;
7225 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7226 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7227 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7229 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7230 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7232 if (gparam->owner && gparam->owner->is_method) {
7233 MonoMethod *method = gparam->owner->owner.method;
7234 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7235 is_type_done = FALSE;
7236 } else if (gparam->owner && !gparam->owner->is_method) {
7237 MonoClass *klass = gparam->owner->owner.klass;
7238 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7239 is_type_done = FALSE;
7243 /* g_assert_not_reached (); */
7244 /* should this be considered an error condition? */
7245 if (is_type_done && !type->byref) {
7246 mono_domain_unlock (domain);
7247 mono_loader_unlock ();
7248 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7251 /* This is stored in vtables/JITted code so it has to be pinned */
7252 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7253 if (!mono_error_ok (error))
7257 mono_g_hash_table_insert (domain->type_hash, type, res);
7259 if (type->type == MONO_TYPE_VOID)
7260 domain->typeof_void = (MonoObject*)res;
7262 mono_domain_unlock (domain);
7263 mono_loader_unlock ();
7268 * mono_method_get_object:
7269 * @domain: an app domain
7271 * @refclass: the reflected type (can be NULL)
7273 * Return an System.Reflection.MonoMethod object representing the method @method.
7275 MonoReflectionMethod*
7276 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7279 MonoReflectionMethod *ret = NULL;
7280 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7281 mono_error_raise_exception (&error);
7286 * mono_method_get_object_checked:
7287 * @domain: an app domain
7289 * @refclass: the reflected type (can be NULL)
7290 * @error: set on error.
7292 * Return an System.Reflection.MonoMethod object representing the method @method.
7293 * Returns NULL and sets @error on error.
7295 MonoReflectionMethod*
7296 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7299 * We use the same C representation for methods and constructors, but the type
7300 * name in C# is different.
7302 MonoReflectionType *rt;
7304 MonoReflectionMethod *ret;
7306 mono_error_init (error);
7308 if (method->is_inflated) {
7309 MonoReflectionGenericMethod *gret;
7312 refclass = method->klass;
7313 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7314 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7315 klass = mono_class_get_mono_generic_cmethod_class ();
7317 klass = mono_class_get_mono_generic_method_class ();
7319 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7320 if (!mono_error_ok (error))
7322 gret->method.method = method;
7324 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7326 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7327 if (!mono_error_ok (error))
7330 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7332 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7336 refclass = method->klass;
7338 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7339 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7340 klass = mono_class_get_mono_cmethod_class ();
7343 klass = mono_class_get_mono_method_class ();
7345 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7346 if (!mono_error_ok (error))
7348 ret->method = method;
7350 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7351 if (!mono_error_ok (error))
7354 MONO_OBJECT_SETREF (ret, reftype, rt);
7356 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7359 g_assert (!mono_error_ok (error));
7364 * mono_method_clear_object:
7366 * Clear the cached reflection objects for the dynamic method METHOD.
7369 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7372 g_assert (method_is_dynamic (method));
7374 klass = method->klass;
7376 clear_cached_object (domain, method, klass);
7377 klass = klass->parent;
7379 /* Added by mono_param_get_objects () */
7380 clear_cached_object (domain, &(method->signature), NULL);
7381 klass = method->klass;
7383 clear_cached_object (domain, &(method->signature), klass);
7384 klass = klass->parent;
7389 * mono_field_get_object:
7390 * @domain: an app domain
7394 * Return an System.Reflection.MonoField object representing the field @field
7397 MonoReflectionField*
7398 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7401 MonoReflectionField *result;
7402 result = mono_field_get_object_checked (domain, klass, field, &error);
7403 mono_error_raise_exception (&error);
7408 * mono_field_get_object_checked:
7409 * @domain: an app domain
7412 * @error: set on error
7414 * Return an System.Reflection.MonoField object representing the field @field
7415 * in class @klass. On error, returns NULL and sets @error.
7417 MonoReflectionField*
7418 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7420 MonoReflectionType *rt;
7421 MonoReflectionField *res;
7423 mono_error_init (error);
7425 CHECK_OBJECT (MonoReflectionField *, field, klass);
7426 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7431 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7433 if (is_field_on_inst (field)) {
7434 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7436 rt = mono_type_get_object_checked (domain, field->type, error);
7437 if (!mono_error_ok (error))
7440 MONO_OBJECT_SETREF (res, type, rt);
7443 rt = mono_type_get_object_checked (domain, field->type, error);
7444 if (!mono_error_ok (error))
7447 MONO_OBJECT_SETREF (res, type, rt);
7449 res->attrs = mono_field_get_flags (field);
7451 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7455 * mono_property_get_object:
7456 * @domain: an app domain
7458 * @property: a property
7460 * Return an System.Reflection.MonoProperty object representing the property @property
7463 MonoReflectionProperty*
7464 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7467 MonoReflectionProperty *result;
7468 result = mono_property_get_object_checked (domain, klass, property, &error);
7469 mono_error_raise_exception (&error);
7474 * mono_property_get_object:
7475 * @domain: an app domain
7477 * @property: a property
7478 * @error: set on error
7480 * Return an System.Reflection.MonoProperty object representing the property @property
7481 * in class @klass. On error returns NULL and sets @error.
7483 MonoReflectionProperty*
7484 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7486 MonoReflectionProperty *res;
7488 mono_error_init (error);
7490 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7491 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7495 res->property = property;
7496 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7500 * mono_event_get_object:
7501 * @domain: an app domain
7505 * Return an System.Reflection.MonoEvent object representing the event @event
7508 MonoReflectionEvent*
7509 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7512 MonoReflectionEvent *result;
7513 result = mono_event_get_object_checked (domain, klass, event, &error);
7514 mono_error_raise_exception (&error);
7519 * mono_event_get_object_checked:
7520 * @domain: an app domain
7523 * @error: set on error
7525 * Return an System.Reflection.MonoEvent object representing the event @event
7526 * in class @klass. On failure sets @error and returns NULL
7528 MonoReflectionEvent*
7529 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7531 MonoReflectionEvent *res;
7532 MonoReflectionMonoEvent *mono_event;
7534 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7535 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7538 mono_event->klass = klass;
7539 mono_event->event = event;
7540 res = (MonoReflectionEvent*)mono_event;
7541 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7545 * mono_get_reflection_missing_object:
7546 * @domain: Domain where the object lives
7548 * Returns the System.Reflection.Missing.Value singleton object
7549 * (of type System.Reflection.Missing).
7551 * Used as the value for ParameterInfo.DefaultValue when Optional
7555 mono_get_reflection_missing_object (MonoDomain *domain)
7558 static MonoClassField *missing_value_field = NULL;
7560 if (!missing_value_field) {
7561 MonoClass *missing_klass;
7562 missing_klass = mono_class_get_missing_class ();
7563 mono_class_init (missing_klass);
7564 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7565 g_assert (missing_value_field);
7567 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7573 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7576 *dbnull = mono_get_dbnull_object (domain);
7581 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7583 if (!*reflection_missing)
7584 *reflection_missing = mono_get_reflection_missing_object (domain);
7585 return *reflection_missing;
7589 * mono_param_get_objects:
7590 * @domain: an app domain
7593 * Return an System.Reflection.ParameterInfo array object representing the parameters
7594 * in the method @method.
7597 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7599 static MonoClass *System_Reflection_ParameterInfo;
7600 static MonoClass *System_Reflection_ParameterInfo_array;
7602 MonoArray *res = NULL;
7603 MonoReflectionMethod *member = NULL;
7604 MonoReflectionParameter *param = NULL;
7605 char **names = NULL, **blobs = NULL;
7606 guint32 *types = NULL;
7607 MonoType *type = NULL;
7608 MonoObject *dbnull = NULL;
7609 MonoObject *missing = NULL;
7610 MonoMarshalSpec **mspecs = NULL;
7611 MonoMethodSignature *sig = NULL;
7612 MonoVTable *pinfo_vtable;
7613 MonoReflectionType *rt;
7616 mono_error_init (&error);
7618 if (!System_Reflection_ParameterInfo_array) {
7621 klass = mono_class_get_mono_parameter_info_class ();
7623 mono_memory_barrier ();
7624 System_Reflection_ParameterInfo = klass;
7627 klass = mono_array_class_get (klass, 1);
7628 mono_memory_barrier ();
7629 System_Reflection_ParameterInfo_array = klass;
7632 sig = mono_method_signature_checked (method, &error);
7633 if (!mono_error_ok (&error))
7636 if (!sig->param_count) {
7637 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7644 /* Note: the cache is based on the address of the signature into the method
7645 * since we already cache MethodInfos with the method as keys.
7647 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7649 member = mono_method_get_object_checked (domain, method, refclass, &error);
7652 names = g_new (char *, sig->param_count);
7653 mono_method_get_param_names (method, (const char **) names);
7655 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7656 mono_method_get_marshal_info (method, mspecs);
7658 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7662 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7663 for (i = 0; i < sig->param_count; ++i) {
7664 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7668 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7672 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7674 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7676 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7678 param->PositionImpl = i;
7679 param->AttrsImpl = sig->params [i]->attrs;
7681 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7682 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7683 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7685 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7689 blobs = g_new0 (char *, sig->param_count);
7690 types = g_new0 (guint32, sig->param_count);
7691 get_default_param_value_blobs (method, blobs, types);
7694 /* Build MonoType for the type from the Constant Table */
7696 type = g_new0 (MonoType, 1);
7697 type->type = (MonoTypeEnum)types [i];
7698 type->data.klass = NULL;
7699 if (types [i] == MONO_TYPE_CLASS)
7700 type->data.klass = mono_defaults.object_class;
7701 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7702 /* For enums, types [i] contains the base type */
7704 type->type = MONO_TYPE_VALUETYPE;
7705 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7707 type->data.klass = mono_class_from_mono_type (type);
7709 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7711 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7712 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7713 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7714 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7716 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7721 if (mspecs [i + 1]) {
7722 MonoReflectionMarshalAsAttribute* mobj;
7723 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7726 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7729 mono_array_setref (res, i, param);
7739 for (i = sig->param_count; i >= 0; i--) {
7741 mono_metadata_free_marshal_spec (mspecs [i]);
7746 mono_error_raise_exception (&error); /* FIXME don't raise here */
7748 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7752 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7754 return mono_param_get_objects_internal (domain, method, NULL);
7758 * mono_method_body_get_object:
7759 * @domain: an app domain
7762 * Return an System.Reflection.MethodBody object representing the method @method.
7764 MonoReflectionMethodBody*
7765 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7768 MonoReflectionMethodBody *ret;
7769 MonoMethodHeader *header;
7771 MonoReflectionType *rt;
7772 guint32 method_rva, local_var_sig_token;
7774 unsigned char format, flags;
7777 /* for compatibility with .net */
7778 if (method_is_dynamic (method))
7779 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7781 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7783 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7784 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7785 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7786 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7787 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7790 image = method->klass->image;
7791 header = mono_method_get_header_checked (method, &error);
7792 mono_error_raise_exception (&error); /* FIXME don't raise here */
7794 if (!image_is_dynamic (image)) {
7795 /* Obtain local vars signature token */
7796 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7797 ptr = mono_image_rva_map (image, method_rva);
7798 flags = *(const unsigned char *) ptr;
7799 format = flags & METHOD_HEADER_FORMAT_MASK;
7801 case METHOD_HEADER_TINY_FORMAT:
7802 local_var_sig_token = 0;
7804 case METHOD_HEADER_FAT_FORMAT:
7808 local_var_sig_token = read32 (ptr);
7811 g_assert_not_reached ();
7814 local_var_sig_token = 0; //FIXME
7816 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7817 mono_error_raise_exception (&error); /* FIXME don't raise here */
7819 ret->init_locals = header->init_locals;
7820 ret->max_stack = header->max_stack;
7821 ret->local_var_sig_token = local_var_sig_token;
7822 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7823 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7826 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7827 for (i = 0; i < header->num_locals; ++i) {
7828 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7829 mono_error_raise_exception (&error); /* FIXME don't raise here */
7831 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7832 mono_error_raise_exception (&error); /* FIXME don't raise here */
7834 MONO_OBJECT_SETREF (info, local_type, rt);
7836 info->is_pinned = header->locals [i]->pinned;
7837 info->local_index = i;
7838 mono_array_setref (ret->locals, i, info);
7842 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7843 for (i = 0; i < header->num_clauses; ++i) {
7844 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7845 mono_error_raise_exception (&error); /* FIXME don't raise here */
7846 MonoExceptionClause *clause = &header->clauses [i];
7848 info->flags = clause->flags;
7849 info->try_offset = clause->try_offset;
7850 info->try_length = clause->try_len;
7851 info->handler_offset = clause->handler_offset;
7852 info->handler_length = clause->handler_len;
7853 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7854 info->filter_offset = clause->data.filter_offset;
7855 else if (clause->data.catch_class) {
7856 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7857 mono_error_raise_exception (&error); /* FIXME don't raise here */
7859 MONO_OBJECT_SETREF (info, catch_type, rt);
7862 mono_array_setref (ret->clauses, i, info);
7865 mono_metadata_free_mh (header);
7866 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7871 * mono_get_dbnull_object:
7872 * @domain: Domain where the object lives
7874 * Returns the System.DBNull.Value singleton object
7876 * Used as the value for ParameterInfo.DefaultValue
7879 mono_get_dbnull_object (MonoDomain *domain)
7882 static MonoClassField *dbnull_value_field = NULL;
7884 if (!dbnull_value_field) {
7885 MonoClass *dbnull_klass;
7886 dbnull_klass = mono_class_get_dbnull_class ();
7887 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7888 g_assert (dbnull_value_field);
7890 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7896 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7898 guint32 param_index, i, lastp, crow = 0;
7899 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7902 MonoClass *klass = method->klass;
7903 MonoImage *image = klass->image;
7904 MonoMethodSignature *methodsig = mono_method_signature (method);
7906 MonoTableInfo *constt;
7907 MonoTableInfo *methodt;
7908 MonoTableInfo *paramt;
7910 if (!methodsig->param_count)
7913 mono_class_init (klass);
7915 if (image_is_dynamic (klass->image)) {
7916 MonoReflectionMethodAux *aux;
7917 if (method->is_inflated)
7918 method = ((MonoMethodInflated*)method)->declaring;
7919 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7920 if (aux && aux->param_defaults) {
7921 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7922 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7927 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7928 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7929 constt = &image->tables [MONO_TABLE_CONSTANT];
7931 idx = mono_method_get_index (method) - 1;
7932 g_assert (idx != -1);
7934 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7935 if (idx + 1 < methodt->rows)
7936 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7938 lastp = paramt->rows + 1;
7940 for (i = param_index; i < lastp; ++i) {
7943 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7944 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7946 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7949 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7954 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7955 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7956 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7963 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7969 MonoType *basetype = type;
7974 klass = mono_class_from_mono_type (type);
7975 if (klass->valuetype) {
7976 object = mono_object_new_checked (domain, klass, &error);
7977 mono_error_raise_exception (&error); /* FIXME don't raise here */
7978 retval = ((gchar *) object + sizeof (MonoObject));
7979 if (klass->enumtype)
7980 basetype = mono_class_enum_basetype (klass);
7985 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7992 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7995 gboolean quoted = FALSE;
7997 memset (assembly, 0, sizeof (MonoAssemblyName));
7998 assembly->culture = "";
7999 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8006 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8017 /* Remove trailing whitespace */
8019 while (*s && g_ascii_isspace (*s))
8022 while (g_ascii_isspace (*p))
8025 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8027 assembly->major = strtoul (p, &s, 10);
8028 if (s == p || *s != '.')
8031 assembly->minor = strtoul (p, &s, 10);
8032 if (s == p || *s != '.')
8035 assembly->build = strtoul (p, &s, 10);
8036 if (s == p || *s != '.')
8039 assembly->revision = strtoul (p, &s, 10);
8043 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8045 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8046 assembly->culture = "";
8049 assembly->culture = p;
8050 while (*p && *p != ',') {
8054 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8056 if (strncmp (p, "null", 4) == 0) {
8061 while (*p && *p != ',') {
8064 len = (p - start + 1);
8065 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8066 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8067 g_strlcpy ((char*)assembly->public_key_token, start, len);
8070 while (*p && *p != ',')
8074 while (g_ascii_isspace (*p) || *p == ',') {
8088 * mono_reflection_parse_type:
8091 * Parse a type name as accepted by the GetType () method and output the info
8092 * extracted in the info structure.
8093 * the name param will be mangled, so, make a copy before passing it to this function.
8094 * The fields in info will be valid until the memory pointed to by name is valid.
8096 * See also mono_type_get_name () below.
8098 * Returns: 0 on parse error.
8101 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8102 MonoTypeNameParse *info)
8104 char *start, *p, *w, *last_point, *startn;
8105 int in_modifiers = 0;
8106 int isbyref = 0, rank = 0, isptr = 0;
8108 start = p = w = name;
8110 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8111 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8112 info->name = info->name_space = NULL;
8113 info->nested = NULL;
8114 info->modifiers = NULL;
8115 info->type_arguments = NULL;
8117 /* last_point separates the namespace from the name */
8120 while (*p == ' ') p++, start++, w++, name++;
8125 *p = 0; /* NULL terminate the name */
8127 info->nested = g_list_append (info->nested, startn);
8128 /* we have parsed the nesting namespace + name */
8132 info->name_space = start;
8134 info->name = last_point + 1;
8136 info->name_space = (char *)"";
8164 info->name_space = start;
8166 info->name = last_point + 1;
8168 info->name_space = (char *)"";
8175 if (isbyref) /* only one level allowed by the spec */
8179 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8183 if (isbyref) /* pointer to ref not okay */
8185 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8190 if (isbyref) /* array of ref and generic ref are not okay */
8192 //Decide if it's an array of a generic argument list
8197 if (*p == ',' || *p == '*' || *p == ']') { //array
8205 else if (*p == '*') /* '*' means unknown lower bound */
8206 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8213 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8215 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8218 info->type_arguments = g_ptr_array_new ();
8220 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8221 gboolean fqname = FALSE;
8223 g_ptr_array_add (info->type_arguments, subinfo);
8225 while (*p == ' ') p++;
8231 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8234 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8235 if (fqname && (*p != ']')) {
8243 while (*p && (*p != ']'))
8251 if (g_ascii_isspace (*aname)) {
8258 !assembly_name_to_aname (&subinfo->assembly, aname))
8260 } else if (fqname && (*p == ']')) {
8282 if (g_ascii_isspace (*p)) {
8289 return 0; /* missing assembly name */
8290 if (!assembly_name_to_aname (&info->assembly, p))
8296 if (info->assembly.name)
8299 // *w = 0; /* terminate class name */
8301 if (!info->name || !*info->name)
8305 /* add other consistency checks */
8311 * mono_identifier_unescape_type_name_chars:
8312 * @identifier: the display name of a mono type
8315 * The name in internal form, that is without escaping backslashes.
8317 * The string is modified in place!
8320 mono_identifier_unescape_type_name_chars(char* identifier)
8325 for (w = r = identifier; *r != 0; r++)
8343 mono_identifier_unescape_info (MonoTypeNameParse* info);
8346 unescape_each_type_argument(void* data, void* user_data)
8348 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8349 mono_identifier_unescape_info (info);
8353 unescape_each_nested_name (void* data, void* user_data)
8355 char* nested_name = (char*) data;
8356 mono_identifier_unescape_type_name_chars(nested_name);
8360 * mono_identifier_unescape_info:
8362 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8366 * Destructively updates the info by unescaping the identifiers that
8367 * comprise the type namespace, name, nested types (if any) and
8368 * generic type arguments (if any).
8370 * The resulting info has the names in internal form.
8374 mono_identifier_unescape_info (MonoTypeNameParse *info)
8378 mono_identifier_unescape_type_name_chars(info->name_space);
8379 mono_identifier_unescape_type_name_chars(info->name);
8380 // but don't escape info->assembly
8381 if (info->type_arguments)
8382 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8384 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8388 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8390 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8392 mono_identifier_unescape_info (info);
8398 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8400 gboolean type_resolve = FALSE;
8402 MonoImage *rootimage = image;
8404 if (info->assembly.name) {
8405 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8406 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8408 * This could happen in the AOT compiler case when the search hook is not
8411 assembly = image->assembly;
8413 /* then we must load the assembly ourselve - see #60439 */
8414 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8418 image = assembly->image;
8419 } else if (!image) {
8420 image = mono_defaults.corlib;
8423 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8424 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8425 image = mono_defaults.corlib;
8426 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8433 * mono_reflection_get_type_internal:
8435 * Returns: may return NULL on success, sets error on failure.
8438 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8443 gboolean bounded = FALSE;
8445 mono_error_init (error);
8447 image = mono_defaults.corlib;
8450 rootimage = mono_defaults.corlib;
8453 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8455 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8460 for (mod = info->nested; mod; mod = mod->next) {
8461 gpointer iter = NULL;
8465 mono_class_init (parent);
8467 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8469 char *nested_name, *nested_nspace;
8470 gboolean match = TRUE;
8472 lastp = strrchr ((const char *)mod->data, '.');
8474 /* Nested classes can have namespaces */
8477 nested_name = g_strdup (lastp + 1);
8478 nspace_len = lastp - (char*)mod->data;
8479 nested_nspace = (char *)g_malloc (nspace_len + 1);
8480 memcpy (nested_nspace, mod->data, nspace_len);
8481 nested_nspace [nspace_len] = '\0';
8484 nested_name = (char *)mod->data;
8485 nested_nspace = NULL;
8488 if (nested_nspace) {
8490 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8493 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8499 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8502 if (strcmp (klass->name, nested_name) != 0)
8507 g_free (nested_name);
8508 g_free (nested_nspace);
8520 if (info->type_arguments) {
8521 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8522 MonoReflectionType *the_type;
8526 for (i = 0; i < info->type_arguments->len; i++) {
8527 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8529 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8530 if (!type_args [i]) {
8536 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8540 instance = mono_reflection_bind_generic_parameters (
8541 the_type, info->type_arguments->len, type_args);
8547 klass = mono_class_from_mono_type (instance);
8550 for (mod = info->modifiers; mod; mod = mod->next) {
8551 modval = GPOINTER_TO_UINT (mod->data);
8552 if (!modval) { /* byref: must be last modifier */
8553 return &klass->this_arg;
8554 } else if (modval == -1) {
8555 klass = mono_ptr_class_get (&klass->byval_arg);
8556 } else if (modval == -2) {
8558 } else { /* array rank */
8559 klass = mono_bounded_array_class_get (klass, modval, bounded);
8563 return &klass->byval_arg;
8567 * mono_reflection_get_type:
8568 * @image: a metadata context
8569 * @info: type description structure
8570 * @ignorecase: flag for case-insensitive string compares
8571 * @type_resolve: whenever type resolve was already tried
8573 * Build a MonoType from the type description in @info.
8578 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8579 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8583 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8585 MonoReflectionAssemblyBuilder *abuilder;
8589 mono_error_init (error);
8590 g_assert (assembly_is_dynamic (assembly));
8591 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8595 /* Enumerate all modules */
8598 if (abuilder->modules) {
8599 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8600 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8601 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8604 if (!mono_error_ok (error))
8609 if (!type && abuilder->loaded_modules) {
8610 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8611 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8612 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8615 if (!mono_error_ok (error))
8624 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8628 MonoReflectionAssembly *assembly;
8632 if (image && image_is_dynamic (image))
8633 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8635 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8637 if (!mono_error_ok (&error))
8638 mono_error_raise_exception (&error); /* FIXME don't raise here */
8642 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8649 *type_resolve = TRUE;
8652 /* Reconstruct the type name */
8653 fullName = g_string_new ("");
8654 if (info->name_space && (info->name_space [0] != '\0'))
8655 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8657 g_string_printf (fullName, "%s", info->name);
8658 for (mod = info->nested; mod; mod = mod->next)
8659 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8661 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8662 mono_error_raise_exception (&error); /* FIXME don't raise here */
8665 if (assembly_is_dynamic (assembly->assembly))
8666 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8667 info, ignorecase, &error);
8669 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8670 info, ignorecase, &error);
8672 g_string_free (fullName, TRUE);
8673 if (!mono_error_ok (&error))
8674 mono_error_raise_exception (&error); /* FIXME don't raise here */
8679 mono_reflection_free_type_info (MonoTypeNameParse *info)
8681 g_list_free (info->modifiers);
8682 g_list_free (info->nested);
8684 if (info->type_arguments) {
8687 for (i = 0; i < info->type_arguments->len; i++) {
8688 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8690 mono_reflection_free_type_info (subinfo);
8691 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8695 g_ptr_array_free (info->type_arguments, TRUE);
8700 * mono_reflection_type_from_name:
8702 * @image: a metadata context (can be NULL).
8704 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8705 * it defaults to get the type from @image or, if @image is NULL or loading
8706 * from it fails, uses corlib.
8710 mono_reflection_type_from_name (char *name, MonoImage *image)
8712 MonoType *type = NULL;
8713 MonoTypeNameParse info;
8716 /* Make a copy since parse_type modifies its argument */
8717 tmp = g_strdup (name);
8719 /*g_print ("requested type %s\n", str);*/
8720 if (mono_reflection_parse_type (tmp, &info)) {
8721 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8725 mono_reflection_free_type_info (&info);
8730 * mono_reflection_get_token:
8732 * Return the metadata token of OBJ which should be an object
8733 * representing a metadata element.
8736 mono_reflection_get_token (MonoObject *obj)
8742 klass = obj->vtable->klass;
8744 if (strcmp (klass->name, "MethodBuilder") == 0) {
8745 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8747 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8748 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8749 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8751 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8752 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8753 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8755 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8756 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8757 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8758 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8759 } else if (strcmp (klass->name, "MonoType") == 0) {
8760 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8761 mono_error_raise_exception (&error); /* FIXME don't raise here */
8762 MonoClass *mc = mono_class_from_mono_type (type);
8763 if (!mono_class_init (mc))
8764 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8766 token = mc->type_token;
8767 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8768 strcmp (klass->name, "MonoMethod") == 0 ||
8769 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8770 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8771 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8772 if (m->method->is_inflated) {
8773 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8774 return inflated->declaring->token;
8776 token = m->method->token;
8778 } else if (strcmp (klass->name, "MonoField") == 0) {
8779 MonoReflectionField *f = (MonoReflectionField*)obj;
8781 if (is_field_on_inst (f->field)) {
8782 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8784 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8785 int field_index = f->field - dgclass->fields;
8788 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8789 obj = dgclass->field_objects [field_index];
8790 return mono_reflection_get_token (obj);
8793 token = mono_class_get_field_token (f->field);
8794 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8795 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8797 token = mono_class_get_property_token (p->property);
8798 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8799 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8801 token = mono_class_get_event_token (p->event);
8802 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8803 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8804 MonoClass *member_class = mono_object_class (p->MemberImpl);
8805 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8807 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8808 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8809 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8812 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8813 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8815 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8816 MonoException *ex = mono_get_exception_not_implemented (msg);
8818 mono_raise_exception (ex);
8825 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8829 int slen = mono_metadata_decode_value (p, &p);
8831 mono_error_init (error);
8833 n = (char *)g_memdup (p, slen + 1);
8835 t = mono_reflection_type_from_name (n, image);
8837 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8838 /* We don't free n, it's consumed by mono_error */
8839 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8845 return mono_class_from_mono_type (t);
8849 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8851 int slen, type = t->type;
8852 MonoClass *tklass = t->data.klass;
8854 mono_error_init (error);
8860 case MONO_TYPE_BOOLEAN: {
8861 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8866 case MONO_TYPE_CHAR:
8868 case MONO_TYPE_I2: {
8869 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8874 #if SIZEOF_VOID_P == 4
8880 case MONO_TYPE_I4: {
8881 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8886 #if SIZEOF_VOID_P == 8
8887 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8891 case MONO_TYPE_I8: {
8892 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8897 case MONO_TYPE_R8: {
8898 double *val = (double *)g_malloc (sizeof (double));
8903 case MONO_TYPE_VALUETYPE:
8904 if (t->data.klass->enumtype) {
8905 type = mono_class_enum_basetype (t->data.klass)->type;
8908 MonoClass *k = t->data.klass;
8910 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8911 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8917 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8920 case MONO_TYPE_STRING:
8921 if (*p == (char)0xFF) {
8925 slen = mono_metadata_decode_value (p, &p);
8927 return mono_string_new_len (mono_domain_get (), p, slen);
8928 case MONO_TYPE_CLASS: {
8929 MonoReflectionType *rt;
8932 if (*p == (char)0xFF) {
8937 slen = mono_metadata_decode_value (p, &p);
8938 n = (char *)g_memdup (p, slen + 1);
8940 t = mono_reflection_type_from_name (n, image);
8942 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8943 /* We don't free n, it's consumed by mono_error */
8944 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8950 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8951 if (!mono_error_ok (error))
8956 case MONO_TYPE_OBJECT: {
8959 MonoClass *subc = NULL;
8964 } else if (subt == 0x0E) {
8965 type = MONO_TYPE_STRING;
8967 } else if (subt == 0x1D) {
8968 MonoType simple_type = {{0}};
8972 type = MONO_TYPE_SZARRAY;
8973 if (etype == 0x50) {
8974 tklass = mono_defaults.systemtype_class;
8975 } else if (etype == 0x55) {
8976 tklass = load_cattr_enum_type (image, p, &p, error);
8977 if (!mono_error_ok (error))
8981 /* See Partition II, Appendix B3 */
8982 etype = MONO_TYPE_OBJECT;
8983 simple_type.type = (MonoTypeEnum)etype;
8984 tklass = mono_class_from_mono_type (&simple_type);
8987 } else if (subt == 0x55) {
8990 slen = mono_metadata_decode_value (p, &p);
8991 n = (char *)g_memdup (p, slen + 1);
8993 t = mono_reflection_type_from_name (n, image);
8995 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8996 /* We don't free n, it's consumed by mono_error */
8997 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
9002 subc = mono_class_from_mono_type (t);
9003 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9004 MonoType simple_type = {{0}};
9005 simple_type.type = (MonoTypeEnum)subt;
9006 subc = mono_class_from_mono_type (&simple_type);
9008 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9010 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9012 if (mono_error_ok (error)) {
9013 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9014 g_assert (!subc->has_references);
9015 if (mono_error_ok (error))
9016 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9022 case MONO_TYPE_SZARRAY: {
9024 guint32 i, alen, basetype;
9027 if (alen == 0xffffffff) {
9031 arr = mono_array_new (mono_domain_get(), tklass, alen);
9032 basetype = tklass->byval_arg.type;
9033 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9034 basetype = mono_class_enum_basetype (tklass)->type;
9039 case MONO_TYPE_BOOLEAN:
9040 for (i = 0; i < alen; i++) {
9041 MonoBoolean val = *p++;
9042 mono_array_set (arr, MonoBoolean, i, val);
9045 case MONO_TYPE_CHAR:
9048 for (i = 0; i < alen; i++) {
9049 guint16 val = read16 (p);
9050 mono_array_set (arr, guint16, i, val);
9057 for (i = 0; i < alen; i++) {
9058 guint32 val = read32 (p);
9059 mono_array_set (arr, guint32, i, val);
9064 for (i = 0; i < alen; i++) {
9067 mono_array_set (arr, double, i, val);
9073 for (i = 0; i < alen; i++) {
9074 guint64 val = read64 (p);
9075 mono_array_set (arr, guint64, i, val);
9079 case MONO_TYPE_CLASS:
9080 case MONO_TYPE_OBJECT:
9081 case MONO_TYPE_STRING:
9082 case MONO_TYPE_SZARRAY:
9083 for (i = 0; i < alen; i++) {
9084 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9085 if (!mono_error_ok (error))
9087 mono_array_setref (arr, i, item);
9091 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9097 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9103 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9105 static MonoMethod *ctor;
9107 void *params [2], *unboxed;
9109 mono_error_init (error);
9112 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9114 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9115 return_val_if_nok (error, NULL);
9118 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9119 return_val_if_nok (error, NULL);
9120 unboxed = mono_object_unbox (retval);
9122 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9123 return_val_if_nok (error, NULL);
9129 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9131 static MonoMethod *ctor;
9133 void *unboxed, *params [2];
9135 mono_error_init (error);
9138 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9141 params [1] = typedarg;
9142 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9143 return_val_if_nok (error, NULL);
9145 unboxed = mono_object_unbox (retval);
9147 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9148 return_val_if_nok (error, NULL);
9154 type_is_reference (MonoType *type)
9156 switch (type->type) {
9157 case MONO_TYPE_BOOLEAN:
9158 case MONO_TYPE_CHAR:
9171 case MONO_TYPE_VALUETYPE:
9179 free_param_data (MonoMethodSignature *sig, void **params) {
9181 for (i = 0; i < sig->param_count; ++i) {
9182 if (!type_is_reference (sig->params [i]))
9183 g_free (params [i]);
9188 * Find the field index in the metadata FieldDef table.
9191 find_field_index (MonoClass *klass, MonoClassField *field) {
9194 for (i = 0; i < klass->field.count; ++i) {
9195 if (field == &klass->fields [i])
9196 return klass->field.first + 1 + i;
9202 * Find the property index in the metadata Property table.
9205 find_property_index (MonoClass *klass, MonoProperty *property) {
9208 for (i = 0; i < klass->ext->property.count; ++i) {
9209 if (property == &klass->ext->properties [i])
9210 return klass->ext->property.first + 1 + i;
9216 * Find the event index in the metadata Event table.
9219 find_event_index (MonoClass *klass, MonoEvent *event) {
9222 for (i = 0; i < klass->ext->event.count; ++i) {
9223 if (event == &klass->ext->events [i])
9224 return klass->ext->event.first + 1 + i;
9230 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9232 const char *p = (const char*)data;
9234 guint32 i, j, num_named;
9236 void *params_buf [32];
9237 void **params = NULL;
9238 MonoMethodSignature *sig;
9239 MonoObject *exc = NULL;
9241 mono_error_init (error);
9243 mono_class_init (method->klass);
9245 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9246 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9251 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9252 if (!mono_error_ok (error)) return NULL;
9254 mono_runtime_invoke_checked (method, attr, NULL, error);
9255 if (!mono_error_ok (error))
9261 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9264 /*g_print ("got attr %s\n", method->klass->name);*/
9266 sig = mono_method_signature (method);
9267 if (sig->param_count < 32) {
9268 params = params_buf;
9269 memset (params, 0, sizeof (void*) * sig->param_count);
9271 /* Allocate using GC so it gets GC tracking */
9272 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9277 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9278 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9279 if (!mono_error_ok (error))
9284 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9285 if (!mono_error_ok (error)) goto fail;
9287 mono_runtime_try_invoke (method, attr, params, &exc, error);
9288 if (!mono_error_ok (error))
9293 num_named = read16 (named);
9295 for (j = 0; j < num_named; j++) {
9297 char *name, named_type, data_type;
9298 named_type = *named++;
9299 data_type = *named++; /* type of data */
9300 if (data_type == MONO_TYPE_SZARRAY)
9301 data_type = *named++;
9302 if (data_type == MONO_TYPE_ENUM) {
9305 type_len = mono_metadata_decode_blob_size (named, &named);
9306 type_name = (char *)g_malloc (type_len + 1);
9307 memcpy (type_name, named, type_len);
9308 type_name [type_len] = 0;
9310 /* FIXME: lookup the type and check type consistency */
9313 name_len = mono_metadata_decode_blob_size (named, &named);
9314 name = (char *)g_malloc (name_len + 1);
9315 memcpy (name, named, name_len);
9316 name [name_len] = 0;
9318 if (named_type == 0x53) {
9319 MonoClassField *field;
9322 /* how this fail is a blackbox */
9323 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9325 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9330 val = load_cattr_value (image, field->type, named, &named, error);
9331 if (!mono_error_ok (error)) {
9333 if (!type_is_reference (field->type))
9338 mono_field_set_value (attr, field, val);
9339 if (!type_is_reference (field->type))
9341 } else if (named_type == 0x54) {
9344 MonoType *prop_type;
9346 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9349 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9355 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9360 /* can we have more that 1 arg in a custom attr named property? */
9361 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9362 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9364 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9365 if (!mono_error_ok (error)) {
9367 if (!type_is_reference (prop_type))
9368 g_free (pparams [0]);
9373 mono_property_set_value (prop, attr, pparams, NULL);
9374 if (!type_is_reference (prop_type))
9375 g_free (pparams [0]);
9380 free_param_data (method->signature, params);
9381 if (params != params_buf)
9382 mono_gc_free_fixed (params);
9387 free_param_data (method->signature, params);
9388 if (params != params_buf)
9389 mono_gc_free_fixed (params);
9391 mono_raise_exception ((MonoException*)exc);
9396 * mono_reflection_create_custom_attr_data_args:
9398 * Create an array of typed and named arguments from the cattr blob given by DATA.
9399 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9400 * NAMED_ARG_INFO will contain information about the named arguments.
9403 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)
9405 MonoArray *typedargs, *namedargs;
9406 MonoClass *attrklass;
9408 const char *p = (const char*)data;
9410 guint32 i, j, num_named;
9411 CattrNamedArg *arginfo = NULL;
9415 *named_arg_info = NULL;
9417 mono_error_init (error);
9419 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9420 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9424 mono_class_init (method->klass);
9426 domain = mono_domain_get ();
9428 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9431 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9435 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9439 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9440 if (!mono_error_ok (error)) {
9441 if (!type_is_reference (mono_method_signature (method)->params [i]))
9446 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9447 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9448 mono_array_setref (typedargs, i, obj);
9450 if (!type_is_reference (mono_method_signature (method)->params [i]))
9455 num_named = read16 (named);
9456 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9458 attrklass = method->klass;
9460 arginfo = g_new0 (CattrNamedArg, num_named);
9461 *named_arg_info = arginfo;
9463 for (j = 0; j < num_named; j++) {
9465 char *name, named_type, data_type;
9466 named_type = *named++;
9467 data_type = *named++; /* type of data */
9468 if (data_type == MONO_TYPE_SZARRAY)
9469 data_type = *named++;
9470 if (data_type == MONO_TYPE_ENUM) {
9473 type_len = mono_metadata_decode_blob_size (named, &named);
9474 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9477 type_name = (char *)g_malloc (type_len + 1);
9478 memcpy (type_name, named, type_len);
9479 type_name [type_len] = 0;
9481 /* FIXME: lookup the type and check type consistency */
9484 name_len = mono_metadata_decode_blob_size (named, &named);
9485 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9487 name = (char *)g_malloc (name_len + 1);
9488 memcpy (name, named, name_len);
9489 name [name_len] = 0;
9491 if (named_type == 0x53) {
9493 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9501 arginfo [j].type = field->type;
9502 arginfo [j].field = field;
9504 val = load_cattr_value (image, field->type, named, &named, error);
9505 if (!mono_error_ok (error)) {
9506 if (!type_is_reference (field->type))
9512 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9513 mono_array_setref (namedargs, j, obj);
9514 if (!type_is_reference (field->type))
9516 } else if (named_type == 0x54) {
9518 MonoType *prop_type;
9519 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9522 if (!prop || !prop->set) {
9527 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9528 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9530 arginfo [j].type = prop_type;
9531 arginfo [j].prop = prop;
9533 val = load_cattr_value (image, prop_type, named, &named, error);
9534 if (!mono_error_ok (error)) {
9535 if (!type_is_reference (prop_type))
9541 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9542 mono_array_setref (namedargs, j, obj);
9543 if (!type_is_reference (prop_type))
9549 *typed_args = typedargs;
9550 *named_args = namedargs;
9553 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9555 *named_arg_info = NULL;
9559 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9562 MonoArray *typedargs, *namedargs;
9565 CattrNamedArg *arginfo = NULL;
9569 mono_error_init (&error);
9577 image = assembly->assembly->image;
9578 method = ref_method->method;
9579 domain = mono_object_domain (ref_method);
9581 if (!mono_class_init (method->klass))
9582 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9584 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9585 if (!mono_error_ok (&error))
9588 if (mono_loader_get_last_error ()) {
9589 mono_error_set_from_loader_error (&error);
9593 if (!typedargs || !namedargs)
9596 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9597 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9598 MonoObject *typedarg;
9600 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9601 if (!is_ok (&error))
9603 mono_array_setref (typedargs, i, typedarg);
9606 for (i = 0; i < mono_array_length (namedargs); ++i) {
9607 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9608 MonoObject *typedarg, *namedarg, *minfo;
9610 if (arginfo [i].prop) {
9611 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9615 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9616 if (!mono_error_ok (&error))
9620 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9621 if (!is_ok (&error))
9623 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9624 if (!is_ok (&error))
9627 mono_array_setref (namedargs, i, namedarg);
9630 *ctor_args = typedargs;
9631 *named_args = namedargs;
9634 mono_error_raise_exception (&error);
9639 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9641 static MonoMethod *ctor;
9647 mono_error_init (error);
9649 g_assert (image->assembly);
9652 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9654 domain = mono_domain_get ();
9655 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9656 return_val_if_nok (error, NULL);
9657 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9658 return_val_if_nok (error, NULL);
9659 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9660 return_val_if_nok (error, NULL);
9661 params [2] = (gpointer)&cattr->data;
9662 params [3] = &cattr->data_size;
9664 mono_runtime_invoke_checked (ctor, attr, params, error);
9665 return_val_if_nok (error, NULL);
9670 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9676 mono_error_init (error);
9679 for (i = 0; i < cinfo->num_attrs; ++i) {
9680 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9684 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9686 for (i = 0; i < cinfo->num_attrs; ++i) {
9687 if (!cinfo->attrs [i].ctor) {
9688 /* The cattr type is not finished yet */
9689 /* We should include the type name but cinfo doesn't contain it */
9690 mono_error_set_type_load_name (error, NULL, NULL, "");
9693 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9694 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9695 if (!mono_error_ok (error))
9697 mono_array_setref (result, n, attr);
9705 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9708 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9709 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9715 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9721 mono_error_init (error);
9722 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9723 for (i = 0; i < cinfo->num_attrs; ++i) {
9724 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9725 return_val_if_nok (error, NULL);
9726 mono_array_setref (result, i, attr);
9732 * mono_custom_attrs_from_index:
9734 * Returns: NULL if no attributes are found or if a loading error occurs.
9737 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9740 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9741 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9745 * mono_custom_attrs_from_index_checked:
9747 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9750 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9752 guint32 mtoken, i, len;
9753 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9755 MonoCustomAttrInfo *ainfo;
9756 GList *tmp, *list = NULL;
9758 MonoCustomAttrEntry* attr;
9760 mono_error_init (error);
9762 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9764 i = mono_metadata_custom_attrs_from_index (image, idx);
9768 while (i < ca->rows) {
9769 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9771 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9774 len = g_list_length (list);
9777 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9778 ainfo->num_attrs = len;
9779 ainfo->image = image;
9780 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9781 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9782 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9783 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9784 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9785 mtoken |= MONO_TOKEN_METHOD_DEF;
9787 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9788 mtoken |= MONO_TOKEN_MEMBER_REF;
9791 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9794 attr = &ainfo->attrs [i - 1];
9795 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9797 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9803 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9804 /*FIXME raising an exception here doesn't make any sense*/
9805 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9810 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9811 attr->data_size = mono_metadata_decode_value (data, &data);
9812 attr->data = (guchar*)data;
9820 mono_custom_attrs_from_method (MonoMethod *method)
9823 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9824 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9829 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9833 mono_error_init (error);
9836 * An instantiated method has the same cattrs as the generic method definition.
9838 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9839 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9841 if (method->is_inflated)
9842 method = ((MonoMethodInflated *) method)->declaring;
9844 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9845 return lookup_custom_attr (method->klass->image, method);
9848 /* Synthetic methods */
9851 idx = mono_method_get_index (method);
9852 idx <<= MONO_CUSTOM_ATTR_BITS;
9853 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9854 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9858 mono_custom_attrs_from_class (MonoClass *klass)
9861 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9862 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9867 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9871 mono_error_init (error);
9873 if (klass->generic_class)
9874 klass = klass->generic_class->container_class;
9876 if (image_is_dynamic (klass->image))
9877 return lookup_custom_attr (klass->image, klass);
9879 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9880 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9881 idx <<= MONO_CUSTOM_ATTR_BITS;
9882 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9884 idx = mono_metadata_token_index (klass->type_token);
9885 idx <<= MONO_CUSTOM_ATTR_BITS;
9886 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9888 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9892 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9895 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9896 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9901 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9905 mono_error_init (error);
9907 if (image_is_dynamic (assembly->image))
9908 return lookup_custom_attr (assembly->image, assembly);
9909 idx = 1; /* there is only one assembly */
9910 idx <<= MONO_CUSTOM_ATTR_BITS;
9911 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9912 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9915 static MonoCustomAttrInfo*
9916 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9920 if (image_is_dynamic (image))
9921 return lookup_custom_attr (image, image);
9922 idx = 1; /* there is only one module */
9923 idx <<= MONO_CUSTOM_ATTR_BITS;
9924 idx |= MONO_CUSTOM_ATTR_MODULE;
9925 return mono_custom_attrs_from_index_checked (image, idx, error);
9929 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9932 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9933 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9938 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9942 if (image_is_dynamic (klass->image)) {
9943 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9944 return lookup_custom_attr (klass->image, property);
9946 idx = find_property_index (klass, property);
9947 idx <<= MONO_CUSTOM_ATTR_BITS;
9948 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9949 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9953 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9956 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9957 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9962 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9966 if (image_is_dynamic (klass->image)) {
9967 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9968 return lookup_custom_attr (klass->image, event);
9970 idx = find_event_index (klass, event);
9971 idx <<= MONO_CUSTOM_ATTR_BITS;
9972 idx |= MONO_CUSTOM_ATTR_EVENT;
9973 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9977 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9980 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9981 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9986 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9989 mono_error_init (error);
9991 if (image_is_dynamic (klass->image)) {
9992 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9993 return lookup_custom_attr (klass->image, field);
9995 idx = find_field_index (klass, field);
9996 idx <<= MONO_CUSTOM_ATTR_BITS;
9997 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9998 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10002 * mono_custom_attrs_from_param:
10003 * @method: handle to the method that we want to retrieve custom parameter information from
10004 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10006 * The result must be released with mono_custom_attrs_free().
10008 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10010 MonoCustomAttrInfo*
10011 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10014 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10015 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10020 * mono_custom_attrs_from_param_checked:
10021 * @method: handle to the method that we want to retrieve custom parameter information from
10022 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10023 * @error: set on error
10025 * The result must be released with mono_custom_attrs_free().
10027 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10029 MonoCustomAttrInfo*
10030 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10033 guint32 i, idx, method_index;
10034 guint32 param_list, param_last, param_pos, found;
10036 MonoReflectionMethodAux *aux;
10038 mono_error_init (error);
10041 * An instantiated method has the same cattrs as the generic method definition.
10043 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10044 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10046 if (method->is_inflated)
10047 method = ((MonoMethodInflated *) method)->declaring;
10049 if (image_is_dynamic (method->klass->image)) {
10050 MonoCustomAttrInfo *res, *ainfo;
10053 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10054 if (!aux || !aux->param_cattr)
10057 /* Need to copy since it will be freed later */
10058 ainfo = aux->param_cattr [param];
10061 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10062 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10063 memcpy (res, ainfo, size);
10067 image = method->klass->image;
10068 method_index = mono_method_get_index (method);
10071 ca = &image->tables [MONO_TABLE_METHOD];
10073 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10074 if (method_index == ca->rows) {
10075 ca = &image->tables [MONO_TABLE_PARAM];
10076 param_last = ca->rows + 1;
10078 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10079 ca = &image->tables [MONO_TABLE_PARAM];
10082 for (i = param_list; i < param_last; ++i) {
10083 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10084 if (param_pos == param) {
10092 idx <<= MONO_CUSTOM_ATTR_BITS;
10093 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10094 return mono_custom_attrs_from_index_checked (image, idx, error);
10098 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10102 for (i = 0; i < ainfo->num_attrs; ++i) {
10103 klass = ainfo->attrs [i].ctor->klass;
10104 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10111 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10114 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10115 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10120 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10126 mono_error_init (error);
10129 for (i = 0; i < ainfo->num_attrs; ++i) {
10130 klass = ainfo->attrs [i].ctor->klass;
10131 if (mono_class_has_parent (klass, attr_klass)) {
10136 if (attr_index == -1)
10139 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10140 if (!mono_error_ok (error))
10142 return mono_array_get (attrs, MonoObject*, attr_index);
10146 * mono_reflection_get_custom_attrs_info:
10147 * @obj: a reflection object handle
10149 * Return the custom attribute info for attributes defined for the
10150 * reflection handle @obj. The objects.
10152 * FIXME this function leaks like a sieve for SRE objects.
10154 MonoCustomAttrInfo*
10155 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10158 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10159 mono_error_assert_ok (&error);
10164 * mono_reflection_get_custom_attrs_info_checked:
10165 * @obj: a reflection object handle
10166 * @error: set on error
10168 * Return the custom attribute info for attributes defined for the
10169 * reflection handle @obj. The objects.
10171 * On failure returns NULL and sets @error.
10173 * FIXME this function leaks like a sieve for SRE objects.
10175 MonoCustomAttrInfo*
10176 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10179 MonoCustomAttrInfo *cinfo = NULL;
10181 mono_error_init (error);
10183 klass = obj->vtable->klass;
10184 if (klass == mono_defaults.monotype_class) {
10185 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10186 return_val_if_nok (error, NULL);
10187 klass = mono_class_from_mono_type (type);
10188 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10189 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10190 return_val_if_nok (error, NULL);
10191 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10192 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10193 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10194 return_val_if_nok (error, NULL);
10195 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10196 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10197 cinfo = mono_custom_attrs_from_module (module->image, error);
10198 return_val_if_nok (error, NULL);
10199 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10200 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10201 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10202 return_val_if_nok (error, NULL);
10203 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10204 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10205 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10206 return_val_if_nok (error, NULL);
10207 } else if (strcmp ("MonoField", klass->name) == 0) {
10208 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10209 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10210 return_val_if_nok (error, NULL);
10211 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10212 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10213 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10214 return_val_if_nok (error, NULL);
10215 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10216 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10217 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10218 return_val_if_nok (error, NULL);
10219 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10220 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10221 MonoClass *member_class = mono_object_class (param->MemberImpl);
10222 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10223 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10224 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10225 return_val_if_nok (error, NULL);
10226 } else if (is_sr_mono_property (member_class)) {
10227 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10228 MonoMethod *method;
10229 if (!(method = prop->property->get))
10230 method = prop->property->set;
10233 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10234 return_val_if_nok (error, NULL);
10236 #ifndef DISABLE_REFLECTION_EMIT
10237 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10238 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10239 return_val_if_nok (error, NULL);
10240 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10241 return_val_if_nok (error, NULL);
10242 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10243 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10244 MonoMethod *method = NULL;
10245 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10246 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10247 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10248 method = ((MonoReflectionMethod *)c->cb)->method;
10250 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));
10252 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10253 return_val_if_nok (error, NULL);
10257 char *type_name = mono_type_get_full_name (member_class);
10258 mono_error_set_generic_error (error, "System", "NotSupportedException",
10259 "Custom attributes on a ParamInfo with member %s are not supported",
10261 g_free (type_name);
10264 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10265 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10266 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10267 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10268 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10269 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10270 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10271 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10272 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10273 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10274 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10275 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10276 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10277 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10278 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10279 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10280 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10281 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10282 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10283 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10284 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10285 return_val_if_nok (error, NULL);
10286 } else { /* handle other types here... */
10287 g_error ("get custom attrs not yet supported for %s", klass->name);
10294 * mono_reflection_get_custom_attrs_by_type:
10295 * @obj: a reflection object handle
10297 * Return an array with all the custom attributes defined of the
10298 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10299 * of that type are returned. The objects are fully build. Return NULL if a loading error
10303 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10306 MonoCustomAttrInfo *cinfo;
10308 mono_error_init (error);
10310 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10311 return_val_if_nok (error, NULL);
10313 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10316 if (!cinfo->cached)
10317 mono_custom_attrs_free (cinfo);
10319 mono_loader_assert_no_error ();
10320 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10327 * mono_reflection_get_custom_attrs:
10328 * @obj: a reflection object handle
10330 * Return an array with all the custom attributes defined of the
10331 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10335 mono_reflection_get_custom_attrs (MonoObject *obj)
10339 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10343 * mono_reflection_get_custom_attrs_data:
10344 * @obj: a reflection obj handle
10346 * Returns an array of System.Reflection.CustomAttributeData,
10347 * which include information about attributes reflected on
10348 * types loaded using the Reflection Only methods
10351 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10355 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10356 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10361 * mono_reflection_get_custom_attrs_data_checked:
10362 * @obj: a reflection obj handle
10363 * @error: set on error
10365 * Returns an array of System.Reflection.CustomAttributeData,
10366 * which include information about attributes reflected on
10367 * types loaded using the Reflection Only methods
10370 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10373 MonoCustomAttrInfo *cinfo;
10375 mono_error_init (error);
10377 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10378 return_val_if_nok (error, NULL);
10380 result = mono_custom_attrs_data_construct (cinfo, error);
10381 return_val_if_nok (error, NULL);
10382 if (!cinfo->cached)
10383 mono_custom_attrs_free (cinfo);
10385 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10387 if (mono_loader_get_last_error ())
10388 mono_error_set_from_loader_error (error);
10393 static MonoReflectionType*
10394 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10396 static MonoMethod *method_get_underlying_system_type = NULL;
10397 MonoReflectionType *rt;
10398 MonoMethod *usertype_method;
10400 mono_error_init (error);
10402 if (!method_get_underlying_system_type)
10403 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10405 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10407 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10414 is_corlib_type (MonoClass *klass)
10416 return klass->image == mono_defaults.corlib;
10419 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10420 static MonoClass *cached_class; \
10421 if (cached_class) \
10422 return cached_class == _class; \
10423 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10424 cached_class = _class; \
10431 #ifndef DISABLE_REFLECTION_EMIT
10433 is_sre_array (MonoClass *klass)
10435 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10439 is_sre_byref (MonoClass *klass)
10441 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10445 is_sre_pointer (MonoClass *klass)
10447 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10451 is_sre_generic_instance (MonoClass *klass)
10453 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10457 is_sre_type_builder (MonoClass *klass)
10459 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10463 is_sre_method_builder (MonoClass *klass)
10465 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10469 is_sre_ctor_builder (MonoClass *klass)
10471 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10475 is_sre_field_builder (MonoClass *klass)
10477 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10481 is_sre_method_on_tb_inst (MonoClass *klass)
10483 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10487 is_sre_ctor_on_tb_inst (MonoClass *klass)
10489 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10493 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10496 mono_error_init (error);
10503 if (is_usertype (ref)) {
10504 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10505 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10511 klass = mono_object_class (ref);
10513 if (is_sre_array (klass)) {
10515 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10516 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10517 return_val_if_nok (error, NULL);
10519 if (sre_array->rank == 0) //single dimentional array
10520 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10522 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10523 sre_array->type.type = res;
10525 } else if (is_sre_byref (klass)) {
10527 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10528 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10529 return_val_if_nok (error, NULL);
10531 res = &mono_class_from_mono_type (base)->this_arg;
10532 sre_byref->type.type = res;
10534 } else if (is_sre_pointer (klass)) {
10536 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10537 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10538 return_val_if_nok (error, NULL);
10540 res = &mono_ptr_class_get (base)->byval_arg;
10541 sre_pointer->type.type = res;
10543 } else if (is_sre_generic_instance (klass)) {
10544 MonoType *res, **types;
10545 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10548 count = mono_array_length (gclass->type_arguments);
10549 types = g_new0 (MonoType*, count);
10550 for (i = 0; i < count; ++i) {
10551 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10552 types [i] = mono_reflection_type_get_handle (t, error);
10553 if (!types[i] || !is_ok (error)) {
10559 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10562 gclass->type.type = res;
10566 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10571 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10574 mono_reflection_type_get_handle (type, &error);
10575 mono_error_set_pending_exception (&error);
10579 mono_reflection_register_with_runtime (MonoReflectionType *type)
10582 MonoType *res = mono_reflection_type_get_handle (type, &error);
10583 mono_error_raise_exception (&error); /* FIXME don't raise here */
10584 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10588 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10590 klass = mono_class_from_mono_type (res);
10592 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10593 mono_domain_lock (domain);
10595 if (!image_is_dynamic (klass->image)) {
10596 mono_class_setup_supertypes (klass);
10598 if (!domain->type_hash)
10599 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10600 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10601 mono_g_hash_table_insert (domain->type_hash, res, type);
10603 mono_domain_unlock (domain);
10604 mono_loader_unlock ();
10608 * LOCKING: Assumes the loader lock is held.
10610 static MonoMethodSignature*
10611 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10613 MonoMethodSignature *sig;
10616 count = parameters? mono_array_length (parameters): 0;
10618 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10619 sig->param_count = count;
10620 sig->sentinelpos = -1; /* FIXME */
10621 for (i = 0; i < count; ++i) {
10622 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10623 mono_error_raise_exception (&error); /* FIXME don't raise here */
10629 * LOCKING: Assumes the loader lock is held.
10631 static MonoMethodSignature*
10632 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10633 MonoMethodSignature *sig;
10635 sig = parameters_to_signature (image, ctor->parameters);
10636 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10637 sig->ret = &mono_defaults.void_class->byval_arg;
10642 * LOCKING: Assumes the loader lock is held.
10644 static MonoMethodSignature*
10645 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10647 MonoMethodSignature *sig;
10649 sig = parameters_to_signature (image, method->parameters);
10650 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10651 if (method->rtype) {
10652 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10653 mono_error_raise_exception (&error); /* FIXME don't raise here */
10655 sig->ret = &mono_defaults.void_class->byval_arg;
10657 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10661 static MonoMethodSignature*
10662 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10664 MonoMethodSignature *sig;
10666 sig = parameters_to_signature (NULL, method->parameters);
10667 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10668 if (method->rtype) {
10669 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10670 mono_error_raise_exception (&error); /* FIXME don't raise here */
10672 sig->ret = &mono_defaults.void_class->byval_arg;
10674 sig->generic_param_count = 0;
10679 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10682 MonoClass *klass = mono_object_class (prop);
10683 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10684 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10685 *name = mono_string_to_utf8 (pb->name);
10686 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10687 mono_error_raise_exception (&error); /* FIXME don't raise here */
10689 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10690 *name = g_strdup (p->property->name);
10691 if (p->property->get)
10692 *type = mono_method_signature (p->property->get)->ret;
10694 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10699 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10702 MonoClass *klass = mono_object_class (field);
10703 if (strcmp (klass->name, "FieldBuilder") == 0) {
10704 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10705 *name = mono_string_to_utf8 (fb->name);
10706 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10707 mono_error_raise_exception (&error); /* FIXME don't raise here */
10709 MonoReflectionField *f = (MonoReflectionField *)field;
10710 *name = g_strdup (mono_field_get_name (f->field));
10711 *type = f->field->type;
10715 #else /* DISABLE_REFLECTION_EMIT */
10718 mono_reflection_register_with_runtime (MonoReflectionType *type)
10720 /* This is empty */
10724 is_sre_type_builder (MonoClass *klass)
10730 is_sre_generic_instance (MonoClass *klass)
10736 init_type_builder_generics (MonoObject *type)
10740 #endif /* !DISABLE_REFLECTION_EMIT */
10744 is_sr_mono_field (MonoClass *klass)
10746 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10750 is_sr_mono_property (MonoClass *klass)
10752 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10756 is_sr_mono_method (MonoClass *klass)
10758 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10762 is_sr_mono_cmethod (MonoClass *klass)
10764 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10768 is_sr_mono_generic_method (MonoClass *klass)
10770 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10774 is_sr_mono_generic_cmethod (MonoClass *klass)
10776 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10780 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10782 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10786 is_usertype (MonoReflectionType *ref)
10788 MonoClass *klass = mono_object_class (ref);
10789 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10792 static MonoReflectionType*
10793 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10795 mono_error_init (error);
10796 if (!type || type->type)
10799 if (is_usertype (type)) {
10800 type = mono_reflection_type_get_underlying_system_type (type, error);
10801 return_val_if_nok (error, NULL);
10802 if (is_usertype (type)) {
10803 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10811 * Encode a value in a custom attribute stream of bytes.
10812 * The value to encode is either supplied as an object in argument val
10813 * (valuetypes are boxed), or as a pointer to the data in the
10815 * @type represents the type of the value
10816 * @buffer is the start of the buffer
10817 * @p the current position in the buffer
10818 * @buflen contains the size of the buffer and is used to return the new buffer size
10819 * if this needs to be realloced.
10820 * @retbuffer and @retp return the start and the position of the buffer
10823 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10826 MonoTypeEnum simple_type;
10828 if ((p-buffer) + 10 >= *buflen) {
10831 newbuf = (char *)g_realloc (buffer, *buflen);
10832 p = newbuf + (p-buffer);
10836 argval = ((char*)arg + sizeof (MonoObject));
10837 simple_type = type->type;
10839 switch (simple_type) {
10840 case MONO_TYPE_BOOLEAN:
10845 case MONO_TYPE_CHAR:
10848 swap_with_size (p, argval, 2, 1);
10854 swap_with_size (p, argval, 4, 1);
10858 swap_with_size (p, argval, 8, 1);
10863 swap_with_size (p, argval, 8, 1);
10866 case MONO_TYPE_VALUETYPE:
10867 if (type->data.klass->enumtype) {
10868 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10871 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10874 case MONO_TYPE_STRING: {
10881 str = mono_string_to_utf8 ((MonoString*)arg);
10882 slen = strlen (str);
10883 if ((p-buffer) + 10 + slen >= *buflen) {
10887 newbuf = (char *)g_realloc (buffer, *buflen);
10888 p = newbuf + (p-buffer);
10891 mono_metadata_encode_value (slen, p, &p);
10892 memcpy (p, str, slen);
10897 case MONO_TYPE_CLASS: {
10900 MonoType *arg_type;
10906 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10907 mono_error_raise_exception (&error); /* FIXME don't raise here */
10908 str = type_get_qualified_name (arg_type, NULL);
10909 slen = strlen (str);
10910 if ((p-buffer) + 10 + slen >= *buflen) {
10914 newbuf = (char *)g_realloc (buffer, *buflen);
10915 p = newbuf + (p-buffer);
10918 mono_metadata_encode_value (slen, p, &p);
10919 memcpy (p, str, slen);
10924 case MONO_TYPE_SZARRAY: {
10926 MonoClass *eclass, *arg_eclass;
10929 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10932 len = mono_array_length ((MonoArray*)arg);
10934 *p++ = (len >> 8) & 0xff;
10935 *p++ = (len >> 16) & 0xff;
10936 *p++ = (len >> 24) & 0xff;
10938 *retbuffer = buffer;
10939 eclass = type->data.klass;
10940 arg_eclass = mono_object_class (arg)->element_class;
10943 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10944 eclass = mono_defaults.object_class;
10946 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10947 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10948 int elsize = mono_class_array_element_size (arg_eclass);
10949 for (i = 0; i < len; ++i) {
10950 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10953 } else if (eclass->valuetype && arg_eclass->valuetype) {
10954 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10955 int elsize = mono_class_array_element_size (eclass);
10956 for (i = 0; i < len; ++i) {
10957 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10961 for (i = 0; i < len; ++i) {
10962 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10967 case MONO_TYPE_OBJECT: {
10973 * The parameter type is 'object' but the type of the actual
10974 * argument is not. So we have to add type information to the blob
10975 * too. This is completely undocumented in the spec.
10979 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10984 klass = mono_object_class (arg);
10986 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10989 } else if (klass->enumtype) {
10991 } else if (klass == mono_defaults.string_class) {
10992 simple_type = MONO_TYPE_STRING;
10995 } else if (klass->rank == 1) {
10997 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10998 /* See Partition II, Appendix B3 */
11001 *p++ = klass->element_class->byval_arg.type;
11002 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
11004 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11005 *p++ = simple_type = klass->byval_arg.type;
11008 g_error ("unhandled type in custom attr");
11010 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11011 slen = strlen (str);
11012 if ((p-buffer) + 10 + slen >= *buflen) {
11016 newbuf = (char *)g_realloc (buffer, *buflen);
11017 p = newbuf + (p-buffer);
11020 mono_metadata_encode_value (slen, p, &p);
11021 memcpy (p, str, slen);
11024 simple_type = mono_class_enum_basetype (klass)->type;
11028 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11031 *retbuffer = buffer;
11035 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11037 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11038 char *str = type_get_qualified_name (type, NULL);
11039 int slen = strlen (str);
11043 * This seems to be optional...
11046 mono_metadata_encode_value (slen, p, &p);
11047 memcpy (p, str, slen);
11050 } else if (type->type == MONO_TYPE_OBJECT) {
11052 } else if (type->type == MONO_TYPE_CLASS) {
11053 /* it should be a type: encode_cattr_value () has the check */
11056 mono_metadata_encode_value (type->type, p, &p);
11057 if (type->type == MONO_TYPE_SZARRAY)
11058 /* See the examples in Partition VI, Annex B */
11059 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11065 #ifndef DISABLE_REFLECTION_EMIT
11067 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11070 /* Preallocate a large enough buffer */
11071 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11072 char *str = type_get_qualified_name (type, NULL);
11073 len = strlen (str);
11075 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11076 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11077 len = strlen (str);
11082 len += strlen (name);
11084 if ((p-buffer) + 20 + len >= *buflen) {
11088 newbuf = (char *)g_realloc (buffer, *buflen);
11089 p = newbuf + (p-buffer);
11093 encode_field_or_prop_type (type, p, &p);
11095 len = strlen (name);
11096 mono_metadata_encode_value (len, p, &p);
11097 memcpy (p, name, len);
11099 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11101 *retbuffer = buffer;
11105 * mono_reflection_get_custom_attrs_blob:
11106 * @ctor: custom attribute constructor
11107 * @ctorArgs: arguments o the constructor
11113 * Creates the blob of data that needs to be saved in the metadata and that represents
11114 * the custom attributed described by @ctor, @ctorArgs etc.
11115 * Returns: a Byte array representing the blob of data.
11118 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11121 MonoMethodSignature *sig;
11126 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11127 /* sig is freed later so allocate it in the heap */
11128 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11130 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11133 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11135 p = buffer = (char *)g_malloc (buflen);
11136 /* write the prolog */
11139 for (i = 0; i < sig->param_count; ++i) {
11140 arg = mono_array_get (ctorArgs, MonoObject*, i);
11141 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11145 i += mono_array_length (properties);
11147 i += mono_array_length (fields);
11149 *p++ = (i >> 8) & 0xff;
11152 for (i = 0; i < mono_array_length (properties); ++i) {
11156 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11157 get_prop_name_and_type (prop, &pname, &ptype);
11158 *p++ = 0x54; /* PROPERTY signature */
11159 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11166 for (i = 0; i < mono_array_length (fields); ++i) {
11170 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11171 get_field_name_and_type (field, &fname, &ftype);
11172 *p++ = 0x53; /* FIELD signature */
11173 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11178 g_assert (p - buffer <= buflen);
11179 buflen = p - buffer;
11180 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11181 p = mono_array_addr (result, char, 0);
11182 memcpy (p, buffer, buflen);
11184 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11190 * mono_reflection_setup_internal_class:
11191 * @tb: a TypeBuilder object
11193 * Creates a MonoClass that represents the TypeBuilder.
11194 * This is a trick that lets us simplify a lot of reflection code
11195 * (and will allow us to support Build and Run assemblies easier).
11198 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11201 MonoClass *klass, *parent;
11203 RESOLVE_TYPE (tb->parent, &error);
11204 mono_error_raise_exception (&error); /* FIXME don't raise here */
11206 mono_loader_lock ();
11209 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11210 if (!is_ok (&error)) {
11211 mono_loader_unlock ();
11212 mono_error_raise_exception (&error); /* FIXME don't raise here */
11214 /* check so we can compile corlib correctly */
11215 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11216 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11217 parent = parent_type->data.klass;
11219 parent = mono_class_from_mono_type (parent_type);
11225 /* the type has already being created: it means we just have to change the parent */
11226 if (tb->type.type) {
11227 klass = mono_class_from_mono_type (tb->type.type);
11228 klass->parent = NULL;
11229 /* fool mono_class_setup_parent */
11230 klass->supertypes = NULL;
11231 mono_class_setup_parent (klass, parent);
11232 mono_class_setup_mono_type (klass);
11233 mono_loader_unlock ();
11237 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11239 klass->image = &tb->module->dynamic_image->image;
11241 klass->inited = 1; /* we lie to the runtime */
11242 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11243 if (!mono_error_ok (&error))
11245 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11246 if (!mono_error_ok (&error))
11248 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11249 klass->flags = tb->attrs;
11251 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11253 klass->element_class = klass;
11255 if (mono_class_get_ref_info (klass) == NULL) {
11257 mono_class_set_ref_info (klass, tb);
11259 /* Put into cache so mono_class_get_checked () will find it.
11260 Skip nested types as those should not be available on the global scope. */
11261 if (!tb->nesting_type)
11262 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11265 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11266 by performing a mono_class_get which does the full resolution.
11268 Working around this semantics would require us to write a lot of code for no clear advantage.
11270 mono_image_append_class_to_reflection_info_set (klass);
11272 g_assert (mono_class_get_ref_info (klass) == tb);
11275 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11277 if (parent != NULL) {
11278 mono_class_setup_parent (klass, parent);
11279 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11280 const char *old_n = klass->name;
11281 /* trick to get relative numbering right when compiling corlib */
11282 klass->name = "BuildingObject";
11283 mono_class_setup_parent (klass, mono_defaults.object_class);
11284 klass->name = old_n;
11287 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11288 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11289 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11290 klass->instance_size = sizeof (MonoObject);
11291 klass->size_inited = 1;
11292 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11295 mono_class_setup_mono_type (klass);
11297 mono_class_setup_supertypes (klass);
11300 * FIXME: handle interfaces.
11303 tb->type.type = &klass->byval_arg;
11305 if (tb->nesting_type) {
11306 g_assert (tb->nesting_type->type);
11307 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11308 if (!is_ok (&error)) goto failure;
11309 klass->nested_in = mono_class_from_mono_type (nesting_type);
11312 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11314 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11316 mono_loader_unlock ();
11320 mono_loader_unlock ();
11321 mono_error_raise_exception (&error);
11325 * mono_reflection_setup_generic_class:
11326 * @tb: a TypeBuilder object
11328 * Setup the generic class before adding the first generic parameter.
11331 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11336 * mono_reflection_create_generic_class:
11337 * @tb: a TypeBuilder object
11339 * Creates the generic class after all generic parameters have been added.
11342 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11348 klass = mono_class_from_mono_type (tb->type.type);
11350 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11352 if (klass->generic_container || (count == 0))
11355 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11357 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11359 klass->generic_container->owner.klass = klass;
11360 klass->generic_container->type_argc = count;
11361 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11363 klass->is_generic = 1;
11365 for (i = 0; i < count; i++) {
11366 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11367 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11368 mono_error_raise_exception (&error); /* FIXME don't raise here */
11369 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11370 klass->generic_container->type_params [i] = *param;
11371 /*Make sure we are a diferent type instance */
11372 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11373 klass->generic_container->type_params [i].info.pklass = NULL;
11374 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11376 g_assert (klass->generic_container->type_params [i].param.owner);
11379 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11383 * mono_reflection_create_internal_class:
11384 * @tb: a TypeBuilder object
11386 * Actually create the MonoClass that is associated with the TypeBuilder.
11389 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11394 klass = mono_class_from_mono_type (tb->type.type);
11396 mono_loader_lock ();
11397 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11398 MonoReflectionFieldBuilder *fb;
11400 MonoType *enum_basetype;
11402 g_assert (tb->fields != NULL);
11403 g_assert (mono_array_length (tb->fields) >= 1);
11405 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11407 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11408 if (!is_ok (&error)) {
11409 mono_loader_unlock ();
11410 mono_error_raise_exception (&error); /* FIXME don't raise here */
11412 if (!mono_type_is_valid_enum_basetype (field_type)) {
11413 mono_loader_unlock ();
11417 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11418 if (!is_ok (&error)) {
11419 mono_loader_unlock ();
11420 mono_error_raise_exception (&error); /* FIXME don't raise here */
11422 klass->element_class = mono_class_from_mono_type (enum_basetype);
11423 if (!klass->element_class)
11424 klass->element_class = mono_class_from_mono_type (enum_basetype);
11427 * get the element_class from the current corlib.
11429 ec = default_class_from_mono_type (enum_basetype);
11430 klass->instance_size = ec->instance_size;
11431 klass->size_inited = 1;
11433 * this is almost safe to do with enums and it's needed to be able
11434 * to create objects of the enum type (for use in SetConstant).
11436 /* FIXME: Does this mean enums can't have method overrides ? */
11437 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11439 mono_loader_unlock ();
11442 static MonoMarshalSpec*
11443 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11444 MonoReflectionMarshal *minfo)
11447 MonoMarshalSpec *res;
11449 res = image_g_new0 (image, MonoMarshalSpec, 1);
11450 res->native = (MonoMarshalNative)minfo->type;
11452 switch (minfo->type) {
11453 case MONO_NATIVE_LPARRAY:
11454 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11455 if (minfo->has_size) {
11456 res->data.array_data.param_num = minfo->param_num;
11457 res->data.array_data.num_elem = minfo->count;
11458 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11461 res->data.array_data.param_num = -1;
11462 res->data.array_data.num_elem = -1;
11463 res->data.array_data.elem_mult = -1;
11467 case MONO_NATIVE_BYVALTSTR:
11468 case MONO_NATIVE_BYVALARRAY:
11469 res->data.array_data.num_elem = minfo->count;
11472 case MONO_NATIVE_CUSTOM:
11473 if (minfo->marshaltyperef) {
11474 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11475 mono_error_raise_exception (&error); /* FIXME don't raise here */
11476 res->data.custom_data.custom_name =
11477 type_get_fully_qualified_name (marshaltyperef);
11479 if (minfo->mcookie)
11480 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11489 #endif /* !DISABLE_REFLECTION_EMIT */
11491 MonoReflectionMarshalAsAttribute*
11492 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11493 MonoMarshalSpec *spec, MonoError *error)
11495 MonoReflectionType *rt;
11496 MonoReflectionMarshalAsAttribute *minfo;
11499 mono_error_init (error);
11501 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11504 minfo->utype = spec->native;
11506 switch (minfo->utype) {
11507 case MONO_NATIVE_LPARRAY:
11508 minfo->array_subtype = spec->data.array_data.elem_type;
11509 minfo->size_const = spec->data.array_data.num_elem;
11510 if (spec->data.array_data.param_num != -1)
11511 minfo->size_param_index = spec->data.array_data.param_num;
11514 case MONO_NATIVE_BYVALTSTR:
11515 case MONO_NATIVE_BYVALARRAY:
11516 minfo->size_const = spec->data.array_data.num_elem;
11519 case MONO_NATIVE_CUSTOM:
11520 if (spec->data.custom_data.custom_name) {
11521 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11523 rt = mono_type_get_object_checked (domain, mtype, error);
11527 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11530 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11532 if (spec->data.custom_data.cookie)
11533 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11543 #ifndef DISABLE_REFLECTION_EMIT
11545 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11546 ReflectionMethodBuilder *rmb,
11547 MonoMethodSignature *sig)
11551 MonoMethodWrapper *wrapperm;
11552 MonoMarshalSpec **specs;
11553 MonoReflectionMethodAux *method_aux;
11558 mono_error_init (&error);
11560 * Methods created using a MethodBuilder should have their memory allocated
11561 * inside the image mempool, while dynamic methods should have their memory
11564 dynamic = rmb->refs != NULL;
11565 image = dynamic ? NULL : klass->image;
11568 g_assert (!klass->generic_class);
11570 mono_loader_lock ();
11572 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11573 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11574 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11576 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11578 wrapperm = (MonoMethodWrapper*)m;
11580 m->dynamic = dynamic;
11582 m->flags = rmb->attrs;
11583 m->iflags = rmb->iattrs;
11584 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11586 m->signature = sig;
11587 m->sre_method = TRUE;
11588 m->skip_visibility = rmb->skip_visibility;
11589 if (rmb->table_idx)
11590 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11592 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11593 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11594 m->string_ctor = 1;
11596 m->signature->pinvoke = 1;
11597 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11598 m->signature->pinvoke = 1;
11600 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11602 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11603 g_assert (mono_error_ok (&error));
11604 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11605 g_assert (mono_error_ok (&error));
11607 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11609 if (image_is_dynamic (klass->image))
11610 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11612 mono_loader_unlock ();
11615 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11616 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11617 MonoMethodHeader *header;
11619 gint32 max_stack, i;
11620 gint32 num_locals = 0;
11621 gint32 num_clauses = 0;
11625 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11626 code_size = rmb->ilgen->code_len;
11627 max_stack = rmb->ilgen->max_stack;
11628 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11629 if (rmb->ilgen->ex_handlers)
11630 num_clauses = method_count_clauses (rmb->ilgen);
11633 code = mono_array_addr (rmb->code, guint8, 0);
11634 code_size = mono_array_length (rmb->code);
11635 /* we probably need to run a verifier on the code... */
11645 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11646 header->code_size = code_size;
11647 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11648 memcpy ((char*)header->code, code, code_size);
11649 header->max_stack = max_stack;
11650 header->init_locals = rmb->init_locals;
11651 header->num_locals = num_locals;
11653 for (i = 0; i < num_locals; ++i) {
11654 MonoReflectionLocalBuilder *lb =
11655 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11657 header->locals [i] = image_g_new0 (image, MonoType, 1);
11658 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11659 mono_error_assert_ok (&error);
11660 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11663 header->num_clauses = num_clauses;
11665 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11666 rmb->ilgen, num_clauses, &error);
11667 mono_error_assert_ok (&error);
11670 wrapperm->header = header;
11673 if (rmb->generic_params) {
11674 int count = mono_array_length (rmb->generic_params);
11675 MonoGenericContainer *container = rmb->generic_container;
11677 g_assert (container);
11679 container->type_argc = count;
11680 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11681 container->owner.method = m;
11682 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11684 m->is_generic = TRUE;
11685 mono_method_set_generic_container (m, container);
11687 for (i = 0; i < count; i++) {
11688 MonoReflectionGenericParam *gp =
11689 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11690 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11691 mono_error_assert_ok (&error);
11692 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11693 container->type_params [i] = *param;
11697 * The method signature might have pointers to generic parameters that belong to other methods.
11698 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11699 * generic parameters.
11701 for (i = 0; i < m->signature->param_count; ++i) {
11702 MonoType *t = m->signature->params [i];
11703 if (t->type == MONO_TYPE_MVAR) {
11704 MonoGenericParam *gparam = t->data.generic_param;
11705 if (gparam->num < count) {
11706 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11707 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11713 if (klass->generic_container) {
11714 container->parent = klass->generic_container;
11715 container->context.class_inst = klass->generic_container->context.class_inst;
11717 container->context.method_inst = mono_get_shared_generic_inst (container);
11721 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11725 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11727 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11728 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11729 for (i = 0; i < rmb->nrefs; ++i)
11730 data [i + 1] = rmb->refs [i];
11735 /* Parameter info */
11738 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11739 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11740 for (i = 0; i <= m->signature->param_count; ++i) {
11741 MonoReflectionParamBuilder *pb;
11742 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11743 if ((i > 0) && (pb->attrs)) {
11744 /* Make a copy since it might point to a shared type structure */
11745 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11746 m->signature->params [i - 1]->attrs = pb->attrs;
11749 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11750 MonoDynamicImage *assembly;
11752 MonoTypeEnum def_type;
11756 if (!method_aux->param_defaults) {
11757 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11758 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11760 assembly = (MonoDynamicImage*)klass->image;
11761 idx = encode_constant (assembly, pb->def_value, &def_type);
11762 /* Copy the data from the blob since it might get realloc-ed */
11763 p = assembly->blob.data + idx;
11764 len = mono_metadata_decode_blob_size (p, &p2);
11766 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11767 method_aux->param_default_types [i] = def_type;
11768 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11772 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11773 g_assert (mono_error_ok (&error));
11776 if (!method_aux->param_cattr)
11777 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11778 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11784 /* Parameter marshalling */
11787 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11788 MonoReflectionParamBuilder *pb;
11789 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11790 if (pb->marshal_info) {
11792 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11793 specs [pb->position] =
11794 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11798 if (specs != NULL) {
11800 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11801 method_aux->param_marshall = specs;
11804 if (image_is_dynamic (klass->image) && method_aux)
11805 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11807 mono_loader_unlock ();
11813 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11815 ReflectionMethodBuilder rmb;
11816 MonoMethodSignature *sig;
11818 mono_loader_lock ();
11819 sig = ctor_builder_to_signature (klass->image, mb);
11820 mono_loader_unlock ();
11822 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11825 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11826 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11828 /* If we are in a generic class, we might be called multiple times from inflate_method */
11829 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11830 /* ilgen is no longer needed */
11834 return mb->mhandle;
11838 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11840 ReflectionMethodBuilder rmb;
11841 MonoMethodSignature *sig;
11843 mono_error_init (error);
11845 mono_loader_lock ();
11846 sig = method_builder_to_signature (klass->image, mb);
11847 mono_loader_unlock ();
11849 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11852 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11853 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11855 /* If we are in a generic class, we might be called multiple times from inflate_method */
11856 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11857 /* ilgen is no longer needed */
11860 return mb->mhandle;
11863 static MonoClassField*
11864 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11866 MonoClassField *field;
11870 field = g_new0 (MonoClassField, 1);
11872 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11873 g_assert (mono_error_ok (&error));
11874 if (fb->attrs || fb->modreq || fb->modopt) {
11875 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11876 if (!is_ok (&error)) {
11878 mono_error_raise_exception (&error); /* FIXME don't raise here */
11880 field->type = mono_metadata_type_dup (NULL, type);
11881 field->type->attrs = fb->attrs;
11883 g_assert (image_is_dynamic (klass->image));
11884 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
11885 g_free (field->type);
11886 if (!is_ok (&error)) {
11888 mono_error_raise_exception (&error); /* FIXME don't raise here */
11890 field->type = mono_metadata_type_dup (klass->image, custom);
11893 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11894 if (!is_ok (&error)) {
11896 mono_error_raise_exception (&error); /* FIXME don't raise here */
11899 if (fb->offset != -1)
11900 field->offset = fb->offset;
11901 field->parent = klass;
11902 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11904 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11911 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11915 MonoReflectionTypeBuilder *tb = NULL;
11916 gboolean is_dynamic = FALSE;
11917 MonoClass *geninst;
11919 mono_loader_lock ();
11921 if (is_sre_type_builder (mono_object_class (type))) {
11922 tb = (MonoReflectionTypeBuilder *) type;
11925 } else if (is_sre_generic_instance (mono_object_class (type))) {
11926 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11927 MonoReflectionType *gtd = rgi->generic_type;
11929 if (is_sre_type_builder (mono_object_class (gtd))) {
11930 tb = (MonoReflectionTypeBuilder *)gtd;
11935 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11936 if (tb && tb->generic_container)
11937 mono_reflection_create_generic_class (tb);
11939 MonoType *t = mono_reflection_type_get_handle (type, &error);
11940 mono_error_raise_exception (&error); /* FIXME don't raise here */
11942 klass = mono_class_from_mono_type (t);
11943 if (!klass->generic_container) {
11944 mono_loader_unlock ();
11948 if (klass->wastypebuilder) {
11949 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11954 mono_loader_unlock ();
11956 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11958 return &geninst->byval_arg;
11962 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11964 MonoGenericClass *gclass;
11965 MonoGenericInst *inst;
11967 g_assert (klass->generic_container);
11969 inst = mono_metadata_get_generic_inst (type_argc, types);
11970 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11972 return mono_generic_class_get_class (gclass);
11975 MonoReflectionMethod*
11976 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11980 MonoMethod *method, *inflated;
11981 MonoMethodInflated *imethod;
11982 MonoGenericContext tmp_context;
11983 MonoGenericInst *ginst;
11984 MonoType **type_argv;
11987 /*FIXME but this no longer should happen*/
11988 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11989 #ifndef DISABLE_REFLECTION_EMIT
11990 MonoReflectionMethodBuilder *mb = NULL;
11994 mb = (MonoReflectionMethodBuilder *) rmethod;
11995 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11996 mono_error_raise_exception (&error); /* FIXME don't raise here */
11997 klass = mono_class_from_mono_type (tb);
11999 method = methodbuilder_to_mono_method (klass, mb, &error);
12001 mono_error_raise_exception (&error); /* FIXME don't raise here */
12003 g_assert_not_reached ();
12007 method = rmethod->method;
12010 klass = method->klass;
12012 if (method->is_inflated)
12013 method = ((MonoMethodInflated *) method)->declaring;
12015 count = mono_method_signature (method)->generic_param_count;
12016 if (count != mono_array_length (types))
12019 type_argv = g_new0 (MonoType *, count);
12020 for (i = 0; i < count; i++) {
12021 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12022 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12023 if (!is_ok (&error)) {
12024 g_free (type_argv);
12025 mono_error_raise_exception (&error); /* FIXME don't raise here */
12028 ginst = mono_metadata_get_generic_inst (count, type_argv);
12029 g_free (type_argv);
12031 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12032 tmp_context.method_inst = ginst;
12034 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12035 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12036 imethod = (MonoMethodInflated *) inflated;
12038 /*FIXME but I think this is no longer necessary*/
12039 if (image_is_dynamic (method->klass->image)) {
12040 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12042 * This table maps metadata structures representing inflated methods/fields
12043 * to the reflection objects representing their generic definitions.
12045 mono_image_lock ((MonoImage*)image);
12046 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12047 mono_image_unlock ((MonoImage*)image);
12050 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12051 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12053 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12054 mono_error_raise_exception (&error); /* FIXME don't raise here */
12058 #ifndef DISABLE_REFLECTION_EMIT
12060 static MonoMethod *
12061 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12063 MonoMethodInflated *imethod;
12064 MonoGenericContext *context;
12068 * With generic code sharing the klass might not be inflated.
12069 * This can happen because classes inflated with their own
12070 * type arguments are "normalized" to the uninflated class.
12072 if (!klass->generic_class)
12075 context = mono_class_get_context (klass);
12077 if (klass->method.count && klass->methods) {
12078 /* Find the already created inflated method */
12079 for (i = 0; i < klass->method.count; ++i) {
12080 g_assert (klass->methods [i]->is_inflated);
12081 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12084 g_assert (i < klass->method.count);
12085 imethod = (MonoMethodInflated*)klass->methods [i];
12088 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12089 mono_error_assert_ok (&error);
12092 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12093 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12095 mono_image_lock ((MonoImage*)image);
12096 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12097 mono_image_unlock ((MonoImage*)image);
12099 return (MonoMethod *) imethod;
12102 static MonoMethod *
12103 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12105 MonoMethod *method;
12108 mono_error_init (error);
12110 MonoClass *type_class = mono_object_class (type);
12112 if (is_sre_generic_instance (type_class)) {
12113 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12114 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12115 return_val_if_nok (error, NULL);
12116 gklass = mono_class_from_mono_type (generic_type);
12117 } else if (is_sre_type_builder (type_class)) {
12118 MonoType *t = mono_reflection_type_get_handle (type, error);
12119 return_val_if_nok (error, NULL);
12120 gklass = mono_class_from_mono_type (t);
12121 } else if (type->type) {
12122 gklass = mono_class_from_mono_type (type->type);
12123 gklass = mono_class_get_generic_type_definition (gklass);
12125 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12128 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12129 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12130 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12132 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12136 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12137 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12140 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12141 method = ((MonoReflectionMethod *) obj)->method;
12143 method = NULL; /* prevent compiler warning */
12144 g_error ("can't handle type %s", obj->vtable->klass->name);
12147 MonoType *t = mono_reflection_type_get_handle (type, error);
12148 return_val_if_nok (error, NULL);
12149 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12152 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12154 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12157 MonoGenericClass *gclass;
12158 MonoDynamicGenericClass *dgclass;
12159 MonoClass *klass, *gklass;
12163 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12164 mono_error_raise_exception (&error); /* FIXME don't raise here */
12165 klass = mono_class_from_mono_type (gtype);
12166 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12167 gclass = gtype->data.generic_class;
12169 if (!gclass->is_dynamic)
12172 dgclass = (MonoDynamicGenericClass *) gclass;
12174 if (dgclass->initialized)
12177 gklass = gclass->container_class;
12178 mono_class_init (gklass);
12180 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12182 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12183 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12184 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12186 for (i = 0; i < dgclass->count_fields; i++) {
12188 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12189 MonoClassField *field, *inflated_field = NULL;
12191 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12192 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12193 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12194 field = ((MonoReflectionField *) obj)->field;
12196 field = NULL; /* prevent compiler warning */
12197 g_assert_not_reached ();
12200 dgclass->fields [i] = *field;
12201 dgclass->fields [i].parent = klass;
12202 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12203 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12204 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12205 dgclass->field_generic_types [i] = field->type;
12206 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12207 dgclass->field_objects [i] = obj;
12209 if (inflated_field) {
12210 g_free (inflated_field);
12212 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12216 dgclass->initialized = TRUE;
12220 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12222 MonoDynamicGenericClass *dgclass;
12225 g_assert (gclass->is_dynamic);
12227 dgclass = (MonoDynamicGenericClass *)gclass;
12229 for (i = 0; i < dgclass->count_fields; ++i) {
12230 MonoClassField *field = dgclass->fields + i;
12231 mono_metadata_free_type (field->type);
12232 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12237 fix_partial_generic_class (MonoClass *klass)
12239 MonoClass *gklass = klass->generic_class->container_class;
12240 MonoDynamicGenericClass *dgclass;
12243 if (klass->wastypebuilder)
12246 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12247 if (klass->parent != gklass->parent) {
12249 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12250 if (mono_error_ok (&error)) {
12251 MonoClass *parent = mono_class_from_mono_type (parent_type);
12252 mono_metadata_free_type (parent_type);
12253 if (parent != klass->parent) {
12254 /*fool mono_class_setup_parent*/
12255 klass->supertypes = NULL;
12256 mono_class_setup_parent (klass, parent);
12259 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12260 mono_error_cleanup (&error);
12261 if (gklass->wastypebuilder)
12262 klass->wastypebuilder = TRUE;
12267 if (!dgclass->initialized)
12270 if (klass->method.count != gklass->method.count) {
12271 klass->method.count = gklass->method.count;
12272 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12274 for (i = 0; i < klass->method.count; i++) {
12276 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12277 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12278 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12282 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12283 klass->interface_count = gklass->interface_count;
12284 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12285 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12287 for (i = 0; i < gklass->interface_count; ++i) {
12289 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12290 mono_error_raise_exception (&error); /* FIXME don't raise here */
12292 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12293 mono_metadata_free_type (iface_type);
12295 ensure_runtime_vtable (klass->interfaces [i], &error);
12296 mono_error_raise_exception (&error); /* FIXME don't raise here */
12298 klass->interfaces_inited = 1;
12301 if (klass->field.count != gklass->field.count) {
12302 klass->field.count = gklass->field.count;
12303 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12305 for (i = 0; i < klass->field.count; i++) {
12307 klass->fields [i] = gklass->fields [i];
12308 klass->fields [i].parent = klass;
12309 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12310 mono_error_raise_exception (&error); /* FIXME don't raise here */
12314 /*We can only finish with this klass once it's parent has as well*/
12315 if (gklass->wastypebuilder)
12316 klass->wastypebuilder = TRUE;
12321 * ensure_generic_class_runtime_vtable:
12322 * @klass a generic class
12323 * @error set on error
12325 * Ensures that the generic container of @klass has a vtable and
12326 * returns TRUE on success. On error returns FALSE and sets @error.
12329 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12331 MonoClass *gklass = klass->generic_class->container_class;
12333 mono_error_init (error);
12335 if (!ensure_runtime_vtable (gklass, error))
12338 fix_partial_generic_class (klass);
12344 * ensure_runtime_vtable:
12346 * @error set on error
12348 * Ensures that @klass has a vtable and returns TRUE on success. On
12349 * error returns FALSE and sets @error.
12352 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12354 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12357 mono_error_init (error);
12359 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12362 if (!ensure_runtime_vtable (klass->parent, error))
12366 num = tb->ctors? mono_array_length (tb->ctors): 0;
12367 num += tb->num_methods;
12368 klass->method.count = num;
12369 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12370 num = tb->ctors? mono_array_length (tb->ctors): 0;
12371 for (i = 0; i < num; ++i) {
12372 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12375 klass->methods [i] = ctor;
12377 num = tb->num_methods;
12379 for (i = 0; i < num; ++i) {
12380 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12383 klass->methods [j++] = meth;
12386 if (tb->interfaces) {
12387 klass->interface_count = mono_array_length (tb->interfaces);
12388 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12389 for (i = 0; i < klass->interface_count; ++i) {
12390 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12391 return_val_if_nok (error, FALSE);
12392 klass->interfaces [i] = mono_class_from_mono_type (iface);
12393 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12396 klass->interfaces_inited = 1;
12398 } else if (klass->generic_class){
12399 if (!ensure_generic_class_runtime_vtable (klass, error))
12403 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12405 for (i = 0; i < klass->method.count; ++i) {
12406 MonoMethod *im = klass->methods [i];
12407 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12408 im->slot = slot_num++;
12411 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12412 mono_class_setup_interface_offsets (klass);
12413 mono_class_setup_interface_id (klass);
12417 * The generic vtable is needed even if image->run is not set since some
12418 * runtime code like ves_icall_Type_GetMethodsByName depends on
12419 * method->slot being defined.
12423 * tb->methods could not be freed since it is used for determining
12424 * overrides during dynamic vtable construction.
12431 mono_reflection_method_get_handle (MonoObject *method)
12434 MonoClass *klass = mono_object_class (method);
12435 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12436 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12437 return sr_method->method;
12439 if (is_sre_method_builder (klass)) {
12440 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12441 return mb->mhandle;
12443 if (is_sre_method_on_tb_inst (klass)) {
12444 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12445 MonoMethod *result;
12446 /*FIXME move this to a proper method and unify with resolve_object*/
12447 if (m->method_args) {
12448 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12449 mono_error_raise_exception (&error); /* FIXME don't raise here */
12451 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12452 mono_error_raise_exception (&error); /* FIXME don't raise here */
12453 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12454 MonoMethod *mono_method;
12456 if (is_sre_method_builder (mono_object_class (m->mb)))
12457 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12458 else if (is_sr_mono_method (mono_object_class (m->mb)))
12459 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12461 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)));
12463 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12468 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12473 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12475 MonoReflectionTypeBuilder *tb;
12477 MonoReflectionMethod *m;
12480 *num_overrides = 0;
12482 g_assert (image_is_dynamic (klass->image));
12484 if (!mono_class_get_ref_info (klass))
12487 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12489 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12493 for (i = 0; i < tb->num_methods; ++i) {
12494 MonoReflectionMethodBuilder *mb =
12495 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12496 if (mb->override_methods)
12497 onum += mono_array_length (mb->override_methods);
12502 *overrides = g_new0 (MonoMethod*, onum * 2);
12505 for (i = 0; i < tb->num_methods; ++i) {
12506 MonoReflectionMethodBuilder *mb =
12507 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12508 if (mb->override_methods) {
12509 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12510 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12512 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12513 (*overrides) [onum * 2 + 1] = mb->mhandle;
12515 g_assert (mb->mhandle);
12523 *num_overrides = onum;
12527 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12529 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12530 MonoReflectionFieldBuilder *fb;
12531 MonoClassField *field;
12532 MonoImage *image = klass->image;
12533 const char *p, *p2;
12535 guint32 len, idx, real_size = 0;
12537 klass->field.count = tb->num_fields;
12538 klass->field.first = 0;
12540 mono_error_init (error);
12542 if (tb->class_size) {
12543 if ((tb->packing_size & 0xffffff00) != 0) {
12544 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12545 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12548 klass->packing_size = tb->packing_size;
12549 real_size = klass->instance_size + tb->class_size;
12552 if (!klass->field.count) {
12553 klass->instance_size = MAX (klass->instance_size, real_size);
12557 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12558 mono_class_alloc_ext (klass);
12559 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12561 This is, guess what, a hack.
12562 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12563 On the static path no field class is resolved, only types are built. This is the right thing to do
12565 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12567 klass->size_inited = 1;
12569 for (i = 0; i < klass->field.count; ++i) {
12570 MonoArray *rva_data;
12571 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12572 field = &klass->fields [i];
12573 field->name = mono_string_to_utf8_image (image, fb->name, error);
12574 if (!mono_error_ok (error))
12577 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12578 return_if_nok (error);
12579 field->type = mono_metadata_type_dup (klass->image, type);
12580 field->type->attrs = fb->attrs;
12582 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12583 return_if_nok (error);
12586 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12587 char *base = mono_array_addr (rva_data, char, 0);
12588 size_t size = mono_array_length (rva_data);
12589 char *data = (char *)mono_image_alloc (klass->image, size);
12590 memcpy (data, base, size);
12591 klass->ext->field_def_values [i].data = data;
12593 if (fb->offset != -1)
12594 field->offset = fb->offset;
12595 field->parent = klass;
12596 fb->handle = field;
12597 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12599 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12600 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12602 if (fb->def_value) {
12603 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12604 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12605 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12606 /* Copy the data from the blob since it might get realloc-ed */
12607 p = assembly->blob.data + idx;
12608 len = mono_metadata_decode_blob_size (p, &p2);
12610 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12611 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12615 klass->instance_size = MAX (klass->instance_size, real_size);
12616 mono_class_layout_fields (klass);
12620 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12622 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12623 MonoReflectionPropertyBuilder *pb;
12624 MonoImage *image = klass->image;
12625 MonoProperty *properties;
12628 mono_error_init (error);
12631 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12633 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12634 klass->ext->property.first = 0;
12636 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12637 klass->ext->properties = properties;
12638 for (i = 0; i < klass->ext->property.count; ++i) {
12639 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12640 properties [i].parent = klass;
12641 properties [i].attrs = pb->attrs;
12642 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12643 if (!mono_error_ok (error))
12645 if (pb->get_method)
12646 properties [i].get = pb->get_method->mhandle;
12647 if (pb->set_method)
12648 properties [i].set = pb->set_method->mhandle;
12650 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12651 if (pb->def_value) {
12653 const char *p, *p2;
12654 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12655 if (!klass->ext->prop_def_values)
12656 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12657 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12658 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12659 /* Copy the data from the blob since it might get realloc-ed */
12660 p = assembly->blob.data + idx;
12661 len = mono_metadata_decode_blob_size (p, &p2);
12663 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12664 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12669 MonoReflectionEvent *
12670 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12673 MonoEvent *event = g_new0 (MonoEvent, 1);
12676 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12677 mono_error_raise_exception (&error); /* FIXME don't raise here */
12678 klass = mono_class_from_mono_type (type);
12680 event->parent = klass;
12681 event->attrs = eb->attrs;
12682 event->name = mono_string_to_utf8 (eb->name);
12683 if (eb->add_method)
12684 event->add = eb->add_method->mhandle;
12685 if (eb->remove_method)
12686 event->remove = eb->remove_method->mhandle;
12687 if (eb->raise_method)
12688 event->raise = eb->raise_method->mhandle;
12690 #ifndef MONO_SMALL_CONFIG
12691 if (eb->other_methods) {
12693 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12694 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12695 MonoReflectionMethodBuilder *mb =
12696 mono_array_get (eb->other_methods,
12697 MonoReflectionMethodBuilder*, j);
12698 event->other [j] = mb->mhandle;
12703 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12704 mono_error_raise_exception (&error); /* FIXME don't raise here */
12709 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12711 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12712 MonoReflectionEventBuilder *eb;
12713 MonoImage *image = klass->image;
12717 mono_error_init (error);
12720 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12722 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12723 klass->ext->event.first = 0;
12725 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12726 klass->ext->events = events;
12727 for (i = 0; i < klass->ext->event.count; ++i) {
12728 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12729 events [i].parent = klass;
12730 events [i].attrs = eb->attrs;
12731 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12732 if (!mono_error_ok (error))
12734 if (eb->add_method)
12735 events [i].add = eb->add_method->mhandle;
12736 if (eb->remove_method)
12737 events [i].remove = eb->remove_method->mhandle;
12738 if (eb->raise_method)
12739 events [i].raise = eb->raise_method->mhandle;
12741 #ifndef MONO_SMALL_CONFIG
12742 if (eb->other_methods) {
12744 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12745 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12746 MonoReflectionMethodBuilder *mb =
12747 mono_array_get (eb->other_methods,
12748 MonoReflectionMethodBuilder*, j);
12749 events [i].other [j] = mb->mhandle;
12753 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12758 remove_instantiations_of_and_ensure_contents (gpointer key,
12760 gpointer user_data)
12762 MonoType *type = (MonoType*)key;
12763 MonoClass *klass = (MonoClass*)user_data;
12765 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12766 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12773 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12775 mono_error_init (error);
12781 for (i = 0; i < mono_array_length (arr); ++i) {
12782 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12783 if (!mono_error_ok (error))
12788 MonoReflectionType*
12789 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12793 MonoDomain* domain;
12794 MonoReflectionType* res;
12797 domain = mono_object_domain (tb);
12798 klass = mono_class_from_mono_type (tb->type.type);
12801 * Check for user defined Type subclasses.
12803 RESOLVE_TYPE (tb->parent, &error);
12804 mono_error_raise_exception (&error); /* FIXME don't raise here */
12805 check_array_for_usertypes (tb->interfaces, &error);
12806 mono_error_raise_exception (&error); /*FIXME don't raise here */
12808 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12809 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12811 RESOLVE_TYPE (fb->type, &error);
12812 mono_error_raise_exception (&error); /* FIXME don't raise here */
12813 check_array_for_usertypes (fb->modreq, &error);
12814 mono_error_raise_exception (&error); /*FIXME don't raise here */
12815 check_array_for_usertypes (fb->modopt, &error);
12816 mono_error_raise_exception (&error); /*FIXME don't raise here */
12817 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12818 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12819 mono_error_raise_exception (&error); /* FIXME don't raise here */
12825 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12826 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12828 RESOLVE_TYPE (mb->rtype, &error);
12829 mono_error_raise_exception (&error); /* FIXME don't raise here */
12830 check_array_for_usertypes (mb->return_modreq, &error);
12831 mono_error_raise_exception (&error); /*FIXME don't raise here */
12832 check_array_for_usertypes (mb->return_modopt, &error);
12833 mono_error_raise_exception (&error); /*FIXME don't raise here */
12834 check_array_for_usertypes (mb->parameters, &error);
12835 mono_error_raise_exception (&error); /*FIXME don't raise here */
12836 if (mb->param_modreq)
12837 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12838 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12839 mono_error_raise_exception (&error); /*FIXME don't raise here */
12841 if (mb->param_modopt)
12842 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12843 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12844 mono_error_raise_exception (&error); /*FIXME don't raise here */
12850 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12851 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12853 check_array_for_usertypes (mb->parameters, &error);
12854 mono_error_raise_exception (&error); /*FIXME don't raise here */
12855 if (mb->param_modreq)
12856 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12857 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12858 mono_error_raise_exception (&error); /*FIXME don't raise here */
12860 if (mb->param_modopt)
12861 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12862 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12863 mono_error_raise_exception (&error); /*FIXME don't raise here */
12869 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12872 * we need to lock the domain because the lock will be taken inside
12873 * So, we need to keep the locking order correct.
12875 mono_loader_lock ();
12876 mono_domain_lock (domain);
12877 if (klass->wastypebuilder) {
12878 mono_domain_unlock (domain);
12879 mono_loader_unlock ();
12881 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12882 mono_error_raise_exception (&error); /* FIXME don't raise here */
12887 * Fields to set in klass:
12888 * the various flags: delegate/unicode/contextbound etc.
12890 klass->flags = tb->attrs;
12891 klass->has_cctor = 1;
12892 klass->has_finalize = 1;
12893 klass->has_finalize_inited = 1;
12895 mono_class_setup_parent (klass, klass->parent);
12896 /* fool mono_class_setup_supertypes */
12897 klass->supertypes = NULL;
12898 mono_class_setup_supertypes (klass);
12899 mono_class_setup_mono_type (klass);
12902 if (!((MonoDynamicImage*)klass->image)->run) {
12903 if (klass->generic_container) {
12904 /* FIXME: The code below can't handle generic classes */
12905 klass->wastypebuilder = TRUE;
12906 mono_loader_unlock ();
12907 mono_domain_unlock (domain);
12909 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12910 mono_error_raise_exception (&error); /* FIXME don't raise here */
12917 /* enums are done right away */
12918 if (!klass->enumtype)
12919 if (!ensure_runtime_vtable (klass, &error))
12922 if (tb->subtypes) {
12923 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12924 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12925 mono_class_alloc_ext (klass);
12926 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12927 if (!is_ok (&error)) goto failure;
12928 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12932 klass->nested_classes_inited = TRUE;
12934 /* fields and object layout */
12935 if (klass->parent) {
12936 if (!klass->parent->size_inited)
12937 mono_class_init (klass->parent);
12938 klass->instance_size = klass->parent->instance_size;
12939 klass->sizes.class_size = 0;
12940 klass->min_align = klass->parent->min_align;
12941 /* if the type has no fields we won't call the field_setup
12942 * routine which sets up klass->has_references.
12944 klass->has_references |= klass->parent->has_references;
12946 klass->instance_size = sizeof (MonoObject);
12947 klass->min_align = 1;
12950 /* FIXME: handle packing_size and instance_size */
12951 typebuilder_setup_fields (klass, &error);
12952 if (!mono_error_ok (&error))
12954 typebuilder_setup_properties (klass, &error);
12955 if (!mono_error_ok (&error))
12958 typebuilder_setup_events (klass, &error);
12959 if (!mono_error_ok (&error))
12962 klass->wastypebuilder = TRUE;
12965 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12966 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12967 * we want to return normal System.MonoType objects, so clear these out from the cache.
12969 * Together with this we must ensure the contents of all instances to match the created type.
12971 if (domain->type_hash && klass->generic_container)
12972 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12974 mono_domain_unlock (domain);
12975 mono_loader_unlock ();
12977 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12978 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12979 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12982 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12983 mono_error_raise_exception (&error); /* FIXME don't raise here */
12985 g_assert (res != (MonoReflectionType*)tb);
12990 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12991 klass->wastypebuilder = TRUE;
12992 mono_domain_unlock (domain);
12993 mono_loader_unlock ();
12994 mono_error_raise_exception (&error);
12999 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13001 MonoGenericParamFull *param;
13006 image = &gparam->tbuilder->module->dynamic_image->image;
13008 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13010 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
13011 g_assert (mono_error_ok (&error));
13012 param->param.num = gparam->index;
13014 if (gparam->mbuilder) {
13015 if (!gparam->mbuilder->generic_container) {
13016 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
13017 mono_error_raise_exception (&error); /* FIXME don't raise here */
13019 MonoClass *klass = mono_class_from_mono_type (tb);
13020 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13021 gparam->mbuilder->generic_container->is_method = TRUE;
13023 * Cannot set owner.method, since the MonoMethod is not created yet.
13024 * Set the image field instead, so type_in_image () works.
13026 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13027 gparam->mbuilder->generic_container->owner.image = klass->image;
13029 param->param.owner = gparam->mbuilder->generic_container;
13030 } else if (gparam->tbuilder) {
13031 if (!gparam->tbuilder->generic_container) {
13032 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
13033 mono_error_raise_exception (&error); /* FIXME don't raise here */
13034 MonoClass *klass = mono_class_from_mono_type (tb);
13035 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13036 gparam->tbuilder->generic_container->owner.klass = klass;
13038 param->param.owner = gparam->tbuilder->generic_container;
13041 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13043 gparam->type.type = &pklass->byval_arg;
13045 mono_class_set_ref_info (pklass, gparam);
13046 mono_image_append_class_to_reflection_info_set (pklass);
13050 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13053 MonoReflectionModuleBuilder *module = sig->module;
13054 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13055 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13060 check_array_for_usertypes (sig->arguments, &error);
13061 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13063 sigbuffer_init (&buf, 32);
13065 sigbuffer_add_value (&buf, 0x07);
13066 sigbuffer_add_value (&buf, na);
13067 if (assembly != NULL){
13068 for (i = 0; i < na; ++i) {
13069 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13070 encode_reflection_type (assembly, type, &buf, &error);
13071 if (!is_ok (&error)) goto fail;
13075 buflen = buf.p - buf.buf;
13076 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13077 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13078 sigbuffer_free (&buf);
13081 sigbuffer_free (&buf);
13082 mono_error_raise_exception (&error); /* FIXME don't raise here */
13087 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13090 MonoDynamicImage *assembly = sig->module->dynamic_image;
13091 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13096 check_array_for_usertypes (sig->arguments, &error);
13097 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13099 sigbuffer_init (&buf, 32);
13101 sigbuffer_add_value (&buf, 0x06);
13102 for (i = 0; i < na; ++i) {
13103 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13104 encode_reflection_type (assembly, type, &buf, &error);
13105 if (!is_ok (&error))
13109 buflen = buf.p - buf.buf;
13110 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13111 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13112 sigbuffer_free (&buf);
13116 sigbuffer_free (&buf);
13117 mono_error_raise_exception (&error); /* FIXME don't raise here */
13122 MonoMethod *handle;
13123 MonoDomain *domain;
13124 } DynamicMethodReleaseData;
13127 * The runtime automatically clean up those after finalization.
13129 static MonoReferenceQueue *dynamic_method_queue;
13132 free_dynamic_method (void *dynamic_method)
13134 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13135 MonoDomain *domain = data->domain;
13136 MonoMethod *method = data->handle;
13139 mono_domain_lock (domain);
13140 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13141 g_hash_table_remove (domain->method_to_dyn_method, method);
13142 mono_domain_unlock (domain);
13143 g_assert (dis_link);
13144 mono_gchandle_free (dis_link);
13146 mono_runtime_free_method (domain, method);
13151 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13154 MonoReferenceQueue *queue;
13155 MonoMethod *handle;
13156 DynamicMethodReleaseData *release_data;
13157 ReflectionMethodBuilder rmb;
13158 MonoMethodSignature *sig;
13160 MonoDomain *domain;
13164 if (mono_runtime_is_shutting_down ())
13165 mono_raise_exception (mono_get_exception_invalid_operation (""));
13167 if (!(queue = dynamic_method_queue)) {
13168 mono_loader_lock ();
13169 if (!(queue = dynamic_method_queue))
13170 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13171 mono_loader_unlock ();
13174 sig = dynamic_method_to_signature (mb);
13176 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13179 * Resolve references.
13182 * Every second entry in the refs array is reserved for storing handle_class,
13183 * which is needed by the ldtoken implementation in the JIT.
13185 rmb.nrefs = mb->nrefs;
13186 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13187 for (i = 0; i < mb->nrefs; i += 2) {
13188 MonoClass *handle_class;
13190 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13192 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13193 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13195 * The referenced DynamicMethod should already be created by the managed
13196 * code, except in the case of circular references. In that case, we store
13197 * method in the refs array, and fix it up later when the referenced
13198 * DynamicMethod is created.
13200 if (method->mhandle) {
13201 ref = method->mhandle;
13203 /* FIXME: GC object stored in unmanaged memory */
13206 /* FIXME: GC object stored in unmanaged memory */
13207 method->referenced_by = g_slist_append (method->referenced_by, mb);
13209 handle_class = mono_defaults.methodhandle_class;
13211 MonoException *ex = NULL;
13212 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13214 ex = mono_get_exception_type_load (NULL, NULL);
13215 else if (mono_security_core_clr_enabled ())
13216 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13220 mono_raise_exception (ex);
13225 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13226 rmb.refs [i + 1] = handle_class;
13230 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13231 if (!is_ok (&error)) {
13233 mono_error_raise_exception (&error); /* FIXME don't raise here */
13235 klass = mono_class_from_mono_type (owner_type);
13237 klass = mono_defaults.object_class;
13240 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13241 release_data = g_new (DynamicMethodReleaseData, 1);
13242 release_data->handle = handle;
13243 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13244 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13245 g_free (release_data);
13247 /* Fix up refs entries pointing at us */
13248 for (l = mb->referenced_by; l; l = l->next) {
13249 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13250 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13253 g_assert (method->mhandle);
13255 data = (gpointer*)wrapper->method_data;
13256 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13257 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13258 data [i + 1] = mb->mhandle;
13261 g_slist_free (mb->referenced_by);
13265 /* ilgen is no longer needed */
13268 domain = mono_domain_get ();
13269 mono_domain_lock (domain);
13270 if (!domain->method_to_dyn_method)
13271 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13272 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13273 mono_domain_unlock (domain);
13276 #endif /* DISABLE_REFLECTION_EMIT */
13280 * mono_reflection_is_valid_dynamic_token:
13282 * Returns TRUE if token is valid.
13286 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13288 return lookup_dyn_token (image, token) != NULL;
13291 MonoMethodSignature *
13292 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13294 MonoMethodSignature *sig;
13295 g_assert (image_is_dynamic (image));
13297 mono_error_init (error);
13299 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13303 return mono_method_signature_checked (method, error);
13306 #ifndef DISABLE_REFLECTION_EMIT
13309 * mono_reflection_lookup_dynamic_token:
13311 * Finish the Builder object pointed to by TOKEN and return the corresponding
13312 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13313 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13316 * LOCKING: Take the loader lock
13319 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13321 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13325 obj = lookup_dyn_token (assembly, token);
13328 g_error ("Could not find required dynamic token 0x%08x", token);
13334 handle_class = &klass;
13335 return resolve_object (image, obj, handle_class, context);
13339 * ensure_complete_type:
13341 * Ensure that KLASS is completed if it is a dynamic type, or references
13345 ensure_complete_type (MonoClass *klass)
13349 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13350 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13352 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13353 mono_error_raise_exception (&error); /* FIXME don't raise here */
13355 // Asserting here could break a lot of code
13356 //g_assert (klass->wastypebuilder);
13359 if (klass->generic_class) {
13360 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13363 for (i = 0; i < inst->type_argc; ++i) {
13364 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13370 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13373 gpointer result = NULL;
13375 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13376 result = mono_string_intern_checked ((MonoString*)obj, &error);
13377 mono_error_raise_exception (&error); /* FIXME don't raise here */
13378 *handle_class = mono_defaults.string_class;
13380 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13381 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13382 mono_error_raise_exception (&error); /* FIXME don't raise here */
13383 MonoClass *mc = mono_class_from_mono_type (type);
13384 if (!mono_class_init (mc))
13385 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13388 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13389 mono_error_raise_exception (&error); /* FIXME don't raise here */
13391 result = mono_class_from_mono_type (inflated);
13392 mono_metadata_free_type (inflated);
13394 result = mono_class_from_mono_type (type);
13396 *handle_class = mono_defaults.typehandle_class;
13398 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13399 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13400 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13401 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13402 result = ((MonoReflectionMethod*)obj)->method;
13405 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13406 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13408 *handle_class = mono_defaults.methodhandle_class;
13410 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13411 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13412 result = mb->mhandle;
13414 /* Type is not yet created */
13415 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13417 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13418 mono_error_raise_exception (&error); /* FIXME don't raise here */
13421 * Hopefully this has been filled in by calling CreateType() on the
13425 * TODO: This won't work if the application finishes another
13426 * TypeBuilder instance instead of this one.
13428 result = mb->mhandle;
13432 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13433 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13435 *handle_class = mono_defaults.methodhandle_class;
13436 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13437 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13439 result = cb->mhandle;
13441 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13443 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13444 mono_error_raise_exception (&error); /* FIXME don't raise here */
13445 result = cb->mhandle;
13449 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13450 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13452 *handle_class = mono_defaults.methodhandle_class;
13453 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13454 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13456 ensure_complete_type (field->parent);
13458 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13459 mono_error_raise_exception (&error); /* FIXME don't raise here */
13461 MonoClass *klass = mono_class_from_mono_type (inflated);
13462 MonoClassField *inflated_field;
13463 gpointer iter = NULL;
13464 mono_metadata_free_type (inflated);
13465 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13466 if (!strcmp (field->name, inflated_field->name))
13469 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13470 result = inflated_field;
13474 *handle_class = mono_defaults.fieldhandle_class;
13476 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13477 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13478 result = fb->handle;
13481 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13483 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13484 mono_error_raise_exception (&error); /* FIXME don't raise here */
13485 result = fb->handle;
13488 if (fb->handle && fb->handle->parent->generic_container) {
13489 MonoClass *klass = fb->handle->parent;
13490 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13491 mono_error_raise_exception (&error); /* FIXME don't raise here */
13493 MonoClass *inflated = mono_class_from_mono_type (type);
13495 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13497 mono_metadata_free_type (type);
13499 *handle_class = mono_defaults.fieldhandle_class;
13500 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13501 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13502 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13503 mono_error_raise_exception (&error); /* FIXME don't raise here */
13506 klass = type->data.klass;
13507 if (klass->wastypebuilder) {
13508 /* Already created */
13512 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13513 mono_error_raise_exception (&error); /* FIXME don't raise here */
13514 result = type->data.klass;
13517 *handle_class = mono_defaults.typehandle_class;
13518 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13519 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13520 MonoMethodSignature *sig;
13523 if (helper->arguments)
13524 nargs = mono_array_length (helper->arguments);
13528 sig = mono_metadata_signature_alloc (image, nargs);
13529 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13530 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13532 if (helper->unmanaged_call_conv) { /* unmanaged */
13533 sig->call_convention = helper->unmanaged_call_conv - 1;
13534 sig->pinvoke = TRUE;
13535 } else if (helper->call_conv & 0x02) {
13536 sig->call_convention = MONO_CALL_VARARG;
13538 sig->call_convention = MONO_CALL_DEFAULT;
13541 sig->param_count = nargs;
13542 /* TODO: Copy type ? */
13543 sig->ret = helper->return_type->type;
13544 for (i = 0; i < nargs; ++i) {
13545 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13546 mono_error_raise_exception (&error); /* FIXME don't raise here */
13550 *handle_class = NULL;
13551 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13552 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13553 /* Already created by the managed code */
13554 g_assert (method->mhandle);
13555 result = method->mhandle;
13556 *handle_class = mono_defaults.methodhandle_class;
13557 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13558 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13559 mono_error_raise_exception (&error); /* FIXME don't raise here */
13560 type = mono_class_inflate_generic_type_checked (type, context, &error);
13561 mono_error_raise_exception (&error); /* FIXME don't raise here */
13563 result = mono_class_from_mono_type (type);
13564 *handle_class = mono_defaults.typehandle_class;
13566 mono_metadata_free_type (type);
13567 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13568 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13569 mono_error_raise_exception (&error); /* FIXME don't raise here */
13570 type = mono_class_inflate_generic_type_checked (type, context, &error);
13571 mono_error_raise_exception (&error); /* FIXME don't raise here */
13573 result = mono_class_from_mono_type (type);
13574 *handle_class = mono_defaults.typehandle_class;
13576 mono_metadata_free_type (type);
13577 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13578 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13579 MonoClass *inflated;
13581 MonoClassField *field;
13583 if (is_sre_field_builder (mono_object_class (f->fb)))
13584 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13585 else if (is_sr_mono_field (mono_object_class (f->fb)))
13586 field = ((MonoReflectionField*)f->fb)->field;
13588 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)));
13590 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13591 mono_error_raise_exception (&error); /* FIXME don't raise here */
13592 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13593 mono_error_raise_exception (&error); /* FIXME don't raise here */
13595 inflated = mono_class_from_mono_type (type);
13597 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13598 ensure_complete_type (field->parent);
13600 mono_metadata_free_type (type);
13601 *handle_class = mono_defaults.fieldhandle_class;
13602 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13603 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13604 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13605 mono_error_raise_exception (&error); /* FIXME don't raise here */
13606 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13607 mono_error_raise_exception (&error); /* FIXME don't raise here */
13609 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13610 MonoMethod *method;
13612 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13613 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13614 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13615 method = ((MonoReflectionMethod *)c->cb)->method;
13617 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)));
13619 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13620 *handle_class = mono_defaults.methodhandle_class;
13621 mono_metadata_free_type (type);
13622 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13623 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13624 if (m->method_args) {
13625 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13626 mono_error_raise_exception (&error); /* FIXME don't raise here */
13628 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13629 mono_error_assert_ok (&error);
13632 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13633 mono_error_raise_exception (&error); /* FIXME don't raise here */
13634 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13635 mono_error_raise_exception (&error); /* FIXME don't raise here */
13637 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13638 MonoMethod *method;
13640 if (is_sre_method_builder (mono_object_class (m->mb)))
13641 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13642 else if (is_sr_mono_method (mono_object_class (m->mb)))
13643 method = ((MonoReflectionMethod *)m->mb)->method;
13645 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)));
13647 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13648 mono_metadata_free_type (type);
13650 *handle_class = mono_defaults.methodhandle_class;
13651 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13652 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13655 MonoMethod *method;
13659 mtype = mono_reflection_type_get_handle (m->parent, &error);
13660 mono_error_raise_exception (&error); /* FIXME don't raise here */
13661 klass = mono_class_from_mono_type (mtype);
13663 /* Find the method */
13665 name = mono_string_to_utf8 (m->name);
13667 while ((method = mono_class_get_methods (klass, &iter))) {
13668 if (!strcmp (method->name, name))
13675 // FIXME: Check parameters/return value etc. match
13678 *handle_class = mono_defaults.methodhandle_class;
13679 } else if (is_sre_array (mono_object_get_class(obj)) ||
13680 is_sre_byref (mono_object_get_class(obj)) ||
13681 is_sre_pointer (mono_object_get_class(obj))) {
13682 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13683 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13684 mono_error_raise_exception (&error); /* FIXME don't raise here */
13687 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13688 mono_error_raise_exception (&error); /* FIXME don't raise here */
13690 result = mono_class_from_mono_type (inflated);
13691 mono_metadata_free_type (inflated);
13693 result = mono_class_from_mono_type (type);
13695 *handle_class = mono_defaults.typehandle_class;
13697 g_print ("%s\n", obj->vtable->klass->name);
13698 g_assert_not_reached ();
13703 #else /* DISABLE_REFLECTION_EMIT */
13706 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13708 g_assert_not_reached ();
13713 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13715 g_assert_not_reached ();
13719 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13721 g_assert_not_reached ();
13725 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13727 g_assert_not_reached ();
13731 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13733 g_assert_not_reached ();
13737 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13739 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13743 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13745 g_assert_not_reached ();
13749 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13751 g_assert_not_reached ();
13754 MonoReflectionModule *
13755 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13757 g_assert_not_reached ();
13762 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13764 g_assert_not_reached ();
13769 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13771 g_assert_not_reached ();
13776 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13777 gboolean create_open_instance, gboolean register_token, MonoError *error)
13779 g_assert_not_reached ();
13784 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13789 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13791 g_assert_not_reached ();
13795 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13798 *num_overrides = 0;
13801 MonoReflectionEvent *
13802 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13804 g_assert_not_reached ();
13808 MonoReflectionType*
13809 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13811 g_assert_not_reached ();
13816 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13818 g_assert_not_reached ();
13822 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13824 g_assert_not_reached ();
13829 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13831 g_assert_not_reached ();
13836 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13841 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13847 mono_reflection_type_get_handle (MonoReflectionType* ref)
13855 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13857 g_assert_not_reached ();
13860 #endif /* DISABLE_REFLECTION_EMIT */
13862 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13863 const static guint32 declsec_flags_map[] = {
13864 0x00000000, /* empty */
13865 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13866 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13867 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13868 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13869 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13870 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13871 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13872 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13873 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13874 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13875 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13876 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13877 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13878 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13879 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13880 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13881 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13882 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13886 * Returns flags that includes all available security action associated to the handle.
13887 * @token: metadata token (either for a class or a method)
13888 * @image: image where resides the metadata.
13891 mono_declsec_get_flags (MonoImage *image, guint32 token)
13893 int index = mono_metadata_declsec_from_index (image, token);
13894 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13895 guint32 result = 0;
13899 /* HasSecurity can be present for other, not specially encoded, attributes,
13900 e.g. SuppressUnmanagedCodeSecurityAttribute */
13904 for (i = index; i < t->rows; i++) {
13905 guint32 cols [MONO_DECL_SECURITY_SIZE];
13907 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13908 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13911 action = cols [MONO_DECL_SECURITY_ACTION];
13912 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13913 result |= declsec_flags_map [action];
13915 g_assert_not_reached ();
13922 * Get the security actions (in the form of flags) associated with the specified method.
13924 * @method: The method for which we want the declarative security flags.
13925 * Return the declarative security flags for the method (only).
13927 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13928 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13931 mono_declsec_flags_from_method (MonoMethod *method)
13933 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13934 /* FIXME: No cache (for the moment) */
13935 guint32 idx = mono_method_get_index (method);
13936 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13937 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13938 return mono_declsec_get_flags (method->klass->image, idx);
13944 * Get the security actions (in the form of flags) associated with the specified class.
13946 * @klass: The class for which we want the declarative security flags.
13947 * Return the declarative security flags for the class.
13949 * Note: We cache the flags inside the MonoClass structure as this will get
13950 * called very often (at least for each method).
13953 mono_declsec_flags_from_class (MonoClass *klass)
13955 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13956 if (!klass->ext || !klass->ext->declsec_flags) {
13959 idx = mono_metadata_token_index (klass->type_token);
13960 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13961 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13962 mono_loader_lock ();
13963 mono_class_alloc_ext (klass);
13964 mono_loader_unlock ();
13965 /* we cache the flags on classes */
13966 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13968 return klass->ext->declsec_flags;
13974 * Get the security actions (in the form of flags) associated with the specified assembly.
13976 * @assembly: The assembly for which we want the declarative security flags.
13977 * Return the declarative security flags for the assembly.
13980 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13982 guint32 idx = 1; /* there is only one assembly */
13983 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13984 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13985 return mono_declsec_get_flags (assembly->image, idx);
13990 * Fill actions for the specific index (which may either be an encoded class token or
13991 * an encoded method token) from the metadata image.
13992 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13995 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13996 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13998 MonoBoolean result = FALSE;
14000 guint32 cols [MONO_DECL_SECURITY_SIZE];
14001 int index = mono_metadata_declsec_from_index (image, token);
14004 t = &image->tables [MONO_TABLE_DECLSECURITY];
14005 for (i = index; i < t->rows; i++) {
14006 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14008 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14011 /* if present only replace (class) permissions with method permissions */
14012 /* if empty accept either class or method permissions */
14013 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14014 if (!actions->demand.blob) {
14015 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14016 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14017 actions->demand.blob = (char*) (blob + 2);
14018 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14021 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14022 if (!actions->noncasdemand.blob) {
14023 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14024 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14025 actions->noncasdemand.blob = (char*) (blob + 2);
14026 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14029 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14030 if (!actions->demandchoice.blob) {
14031 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14032 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14033 actions->demandchoice.blob = (char*) (blob + 2);
14034 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14044 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14045 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14047 guint32 idx = mono_metadata_token_index (klass->type_token);
14048 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14049 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14050 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14054 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14055 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14057 guint32 idx = mono_method_get_index (method);
14058 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14059 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14060 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14064 * Collect all actions (that requires to generate code in mini) assigned for
14065 * the specified method.
14066 * Note: Don't use the content of actions if the function return FALSE.
14069 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14071 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14072 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14073 MonoBoolean result = FALSE;
14076 /* quick exit if no declarative security is present in the metadata */
14077 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14080 /* we want the original as the wrapper is "free" of the security informations */
14081 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14082 method = mono_marshal_method_from_wrapper (method);
14087 /* First we look for method-level attributes */
14088 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14089 mono_class_init (method->klass);
14090 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14092 result = mono_declsec_get_method_demands_params (method, demands,
14093 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14096 /* Here we use (or create) the class declarative cache to look for demands */
14097 flags = mono_declsec_flags_from_class (method->klass);
14098 if (flags & mask) {
14100 mono_class_init (method->klass);
14101 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14103 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14104 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14107 /* The boolean return value is used as a shortcut in case nothing needs to
14108 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14114 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14116 * Note: Don't use the content of actions if the function return FALSE.
14119 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14121 MonoBoolean result = FALSE;
14124 /* quick exit if no declarative security is present in the metadata */
14125 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14128 /* we want the original as the wrapper is "free" of the security informations */
14129 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14130 method = mono_marshal_method_from_wrapper (method);
14135 /* results are independant - zeroize both */
14136 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14137 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14139 /* First we look for method-level attributes */
14140 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14141 mono_class_init (method->klass);
14143 result = mono_declsec_get_method_demands_params (method, cmethod,
14144 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14147 /* Here we use (or create) the class declarative cache to look for demands */
14148 flags = mono_declsec_flags_from_class (method->klass);
14149 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14150 mono_class_init (method->klass);
14152 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14153 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14160 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14162 * @klass The inherited class - this is the class that provides the security check (attributes)
14164 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14166 * Note: Don't use the content of actions if the function return FALSE.
14169 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14171 MonoBoolean result = FALSE;
14174 /* quick exit if no declarative security is present in the metadata */
14175 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14178 /* Here we use (or create) the class declarative cache to look for demands */
14179 flags = mono_declsec_flags_from_class (klass);
14180 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14181 mono_class_init (klass);
14182 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14184 result |= mono_declsec_get_class_demands_params (klass, demands,
14185 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14192 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14194 * Note: Don't use the content of actions if the function return FALSE.
14197 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14199 /* quick exit if no declarative security is present in the metadata */
14200 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14203 /* we want the original as the wrapper is "free" of the security informations */
14204 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14205 method = mono_marshal_method_from_wrapper (method);
14210 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14211 mono_class_init (method->klass);
14212 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14214 return mono_declsec_get_method_demands_params (method, demands,
14215 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14222 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14224 guint32 cols [MONO_DECL_SECURITY_SIZE];
14228 int index = mono_metadata_declsec_from_index (image, token);
14232 t = &image->tables [MONO_TABLE_DECLSECURITY];
14233 for (i = index; i < t->rows; i++) {
14234 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14236 /* shortcut - index are ordered */
14237 if (token != cols [MONO_DECL_SECURITY_PARENT])
14240 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14241 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14242 entry->blob = (char*) (metadata + 2);
14243 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14252 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14254 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14255 guint32 idx = mono_method_get_index (method);
14256 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14257 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14258 return get_declsec_action (method->klass->image, idx, action, entry);
14264 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14267 guint32 flags = mono_declsec_flags_from_class (klass);
14268 if (declsec_flags_map [action] & flags) {
14269 guint32 idx = mono_metadata_token_index (klass->type_token);
14270 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14271 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14272 return get_declsec_action (klass->image, idx, action, entry);
14278 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14280 guint32 idx = 1; /* there is only one assembly */
14281 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14282 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14284 return get_declsec_action (assembly->image, idx, action, entry);
14288 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14291 MonoObject *res, *exc;
14293 static MonoMethod *method = NULL;
14295 if (method == NULL) {
14296 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14301 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14302 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14304 g_assert (mono_class_get_ref_info (klass));
14305 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14307 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14308 mono_error_raise_exception (&error); /* FIXME don't raise here */
14310 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14312 if (exc || !mono_error_ok (&error)) {
14313 mono_error_cleanup (&error);
14316 return *(MonoBoolean*)mono_object_unbox (res);
14320 * mono_reflection_type_get_type:
14321 * @reftype: the System.Type object
14323 * Returns the MonoType* associated with the C# System.Type object @reftype.
14326 mono_reflection_type_get_type (MonoReflectionType *reftype)
14328 g_assert (reftype);
14331 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14332 mono_error_assert_ok (&error);
14337 * mono_reflection_assembly_get_assembly:
14338 * @refassembly: the System.Reflection.Assembly object
14340 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14343 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14345 g_assert (refassembly);
14347 return refassembly->assembly;