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)
3844 MonoMethodSignature *sig;
3848 name = mono_string_to_utf8 (m->name);
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);
3857 mono_error_raise_exception (&error); /* FIXME don't raise here */
3859 sig->ret = &mono_defaults.void_class->byval_arg;
3861 mtype = mono_reflection_type_get_handle (m->parent, &error);
3862 mono_error_raise_exception (&error); /* FIXME don't raise here */
3864 for (i = 0; i < nparams; ++i) {
3865 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3866 mono_error_raise_exception (&error); /* FIXME don't raise here */
3869 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3870 am = (ArrayMethod *)tmp->data;
3871 if (strcmp (name, am->name) == 0 &&
3872 mono_metadata_type_equal (am->parent, mtype) &&
3873 mono_metadata_signature_equal (am->sig, sig)) {
3876 m->table_idx = am->token & 0xffffff;
3880 am = g_new0 (ArrayMethod, 1);
3884 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3885 method_encode_signature (assembly, sig));
3886 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3887 m->table_idx = am->token & 0xffffff;
3892 * Insert into the metadata tables all the info about the TypeBuilder tb.
3893 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3896 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3898 MonoDynamicTable *table;
3900 int i, is_object = 0, is_system = 0;
3903 mono_error_init (error);
3905 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3906 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3907 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3908 n = mono_string_to_utf8 (tb->name);
3909 if (strcmp (n, "Object") == 0)
3911 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3913 n = mono_string_to_utf8 (tb->nspace);
3914 if (strcmp (n, "System") == 0)
3916 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3918 if (tb->parent && !(is_system && is_object) &&
3919 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3920 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3921 return_val_if_nok (error, FALSE);
3922 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3924 values [MONO_TYPEDEF_EXTENDS] = 0;
3926 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3927 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3930 * if we have explicitlayout or sequentiallayouts, output data in the
3931 * ClassLayout table.
3933 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3934 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3935 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3937 alloc_table (table, table->rows);
3938 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3939 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3940 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3941 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3944 /* handle interfaces */
3945 if (tb->interfaces) {
3946 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3948 table->rows += mono_array_length (tb->interfaces);
3949 alloc_table (table, table->rows);
3950 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3951 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3952 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3953 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3954 return_val_if_nok (error, FALSE);
3955 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3956 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3957 values += MONO_INTERFACEIMPL_SIZE;
3963 table = &assembly->tables [MONO_TABLE_FIELD];
3964 table->rows += tb->num_fields;
3965 alloc_table (table, table->rows);
3966 for (i = 0; i < tb->num_fields; ++i) {
3967 mono_image_get_field_info (
3968 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3969 return_val_if_nok (error, FALSE);
3973 /* handle constructors */
3975 table = &assembly->tables [MONO_TABLE_METHOD];
3976 table->rows += mono_array_length (tb->ctors);
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3979 if (!mono_image_get_ctor_info (domain,
3980 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3986 /* handle methods */
3988 table = &assembly->tables [MONO_TABLE_METHOD];
3989 table->rows += tb->num_methods;
3990 alloc_table (table, table->rows);
3991 for (i = 0; i < tb->num_methods; ++i) {
3992 if (!mono_image_get_method_info (
3993 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3998 /* Do the same with properties etc.. */
3999 if (tb->events && mono_array_length (tb->events)) {
4000 table = &assembly->tables [MONO_TABLE_EVENT];
4001 table->rows += mono_array_length (tb->events);
4002 alloc_table (table, table->rows);
4003 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4005 alloc_table (table, table->rows);
4006 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4007 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4008 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4009 for (i = 0; i < mono_array_length (tb->events); ++i) {
4010 mono_image_get_event_info (
4011 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4012 return_val_if_nok (error, FALSE);
4015 if (tb->properties && mono_array_length (tb->properties)) {
4016 table = &assembly->tables [MONO_TABLE_PROPERTY];
4017 table->rows += mono_array_length (tb->properties);
4018 alloc_table (table, table->rows);
4019 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4021 alloc_table (table, table->rows);
4022 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4023 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4024 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4025 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4026 mono_image_get_property_info (
4027 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4028 return_val_if_nok (error, FALSE);
4032 /* handle generic parameters */
4033 if (tb->generic_params) {
4034 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4035 table->rows += mono_array_length (tb->generic_params);
4036 alloc_table (table, table->rows);
4037 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4038 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4040 mono_image_get_generic_param_info (
4041 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4045 mono_image_add_decl_security (assembly,
4046 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4049 MonoDynamicTable *ntable;
4051 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4052 ntable->rows += mono_array_length (tb->subtypes);
4053 alloc_table (ntable, ntable->rows);
4054 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4056 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4057 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4059 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4060 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4061 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4062 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4063 mono_string_to_utf8 (tb->name), tb->table_idx,
4064 ntable->next_idx, ntable->rows);*/
4065 values += MONO_NESTED_CLASS_SIZE;
4075 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4079 mono_ptr_array_append (*types, type);
4081 if (!type->subtypes)
4084 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4085 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4086 collect_types (types, subtype);
4091 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4093 if ((*type1)->table_idx < (*type2)->table_idx)
4096 if ((*type1)->table_idx > (*type2)->table_idx)
4103 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4106 mono_error_init (error);
4109 for (i = 0; i < mono_array_length (pinfo); ++i) {
4110 MonoReflectionParamBuilder *pb;
4111 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4114 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4122 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4125 mono_error_init (error);
4127 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4130 for (i = 0; i < tb->num_fields; ++i) {
4131 MonoReflectionFieldBuilder* fb;
4132 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4133 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4138 for (i = 0; i < mono_array_length (tb->events); ++i) {
4139 MonoReflectionEventBuilder* eb;
4140 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4141 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4145 if (tb->properties) {
4146 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4147 MonoReflectionPropertyBuilder* pb;
4148 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4149 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4154 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4155 MonoReflectionCtorBuilder* cb;
4156 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4157 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4158 !params_add_cattrs (assembly, cb->pinfo, error))
4164 for (i = 0; i < tb->num_methods; ++i) {
4165 MonoReflectionMethodBuilder* mb;
4166 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4167 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4168 !params_add_cattrs (assembly, mb->pinfo, error))
4174 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4175 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4184 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4188 mono_error_init (error);
4190 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4193 if (moduleb->global_methods) {
4194 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4195 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4196 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4197 !params_add_cattrs (assembly, mb->pinfo, error))
4202 if (moduleb->global_fields) {
4203 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4204 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4205 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4210 if (moduleb->types) {
4211 for (i = 0; i < moduleb->num_types; ++i) {
4212 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4221 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4223 MonoDynamicTable *table;
4227 char *b = blob_size;
4230 table = &assembly->tables [MONO_TABLE_FILE];
4232 alloc_table (table, table->rows);
4233 values = table->values + table->next_idx * MONO_FILE_SIZE;
4234 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4235 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4236 if (image_is_dynamic (module->image)) {
4237 /* This depends on the fact that the main module is emitted last */
4238 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4239 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4242 path = g_strdup (module->image->name);
4244 mono_sha1_get_digest_from_file (path, hash);
4247 mono_metadata_encode_value (20, b, &b);
4248 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4249 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4254 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4256 MonoDynamicTable *table;
4259 table = &assembly->tables [MONO_TABLE_MODULE];
4260 mb->table_idx = table->next_idx ++;
4261 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4262 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4265 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4266 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4267 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4268 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4272 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4273 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4275 MonoDynamicTable *table;
4279 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4280 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4283 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4285 alloc_table (table, table->rows);
4286 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4288 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4289 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4290 if (klass->nested_in)
4291 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4293 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4294 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4295 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4297 res = table->next_idx;
4301 /* Emit nested types */
4302 if (klass->ext && klass->ext->nested_classes) {
4305 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4306 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4313 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4314 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4320 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4321 mono_error_raise_exception (&error); /* FIXME don't raise here */
4323 klass = mono_class_from_mono_type (t);
4325 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4327 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4328 parent_index, assembly);
4332 * We need to do this ourselves since klass->nested_classes is not set up.
4335 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4336 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4341 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4342 guint32 module_index, MonoDynamicImage *assembly)
4344 MonoImage *image = module->image;
4348 t = &image->tables [MONO_TABLE_TYPEDEF];
4350 for (i = 0; i < t->rows; ++i) {
4352 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4353 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4355 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4356 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4361 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4363 MonoDynamicTable *table;
4365 guint32 scope, scope_idx, impl, current_idx;
4366 gboolean forwarder = TRUE;
4367 gpointer iter = NULL;
4370 if (klass->nested_in) {
4371 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4374 scope = resolution_scope_from_image (assembly, klass->image);
4375 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4376 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4377 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4380 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4383 alloc_table (table, table->rows);
4384 current_idx = table->next_idx;
4385 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4387 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4388 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4389 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4390 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4391 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4395 while ((nested = mono_class_get_nested_types (klass, &iter)))
4396 add_exported_type (assemblyb, assembly, nested, current_idx);
4400 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4406 if (!assemblyb->type_forwarders)
4409 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4410 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4415 type = mono_reflection_type_get_handle (t, &error);
4416 mono_error_assert_ok (&error);
4419 klass = mono_class_from_mono_type (type);
4421 add_exported_type (assemblyb, assembly, klass, 0);
4425 #define align_pointer(base,p)\
4427 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4429 (p) += 4 - (__diff & 3);\
4433 compare_constants (const void *a, const void *b)
4435 const guint32 *a_values = (const guint32 *)a;
4436 const guint32 *b_values = (const guint32 *)b;
4437 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4441 compare_semantics (const void *a, const void *b)
4443 const guint32 *a_values = (const guint32 *)a;
4444 const guint32 *b_values = (const guint32 *)b;
4445 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4448 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4452 compare_custom_attrs (const void *a, const void *b)
4454 const guint32 *a_values = (const guint32 *)a;
4455 const guint32 *b_values = (const guint32 *)b;
4457 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4461 compare_field_marshal (const void *a, const void *b)
4463 const guint32 *a_values = (const guint32 *)a;
4464 const guint32 *b_values = (const guint32 *)b;
4466 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4470 compare_nested (const void *a, const void *b)
4472 const guint32 *a_values = (const guint32 *)a;
4473 const guint32 *b_values = (const guint32 *)b;
4475 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4479 compare_genericparam (const void *a, const void *b)
4482 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4483 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4485 if ((*b_entry)->owner == (*a_entry)->owner) {
4486 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4487 mono_error_assert_ok (&error);
4488 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4489 mono_error_assert_ok (&error);
4491 mono_type_get_generic_param_num (a_type) -
4492 mono_type_get_generic_param_num (b_type);
4494 return (*a_entry)->owner - (*b_entry)->owner;
4498 compare_declsecurity_attrs (const void *a, const void *b)
4500 const guint32 *a_values = (const guint32 *)a;
4501 const guint32 *b_values = (const guint32 *)b;
4503 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4507 compare_interface_impl (const void *a, const void *b)
4509 const guint32 *a_values = (const guint32 *)a;
4510 const guint32 *b_values = (const guint32 *)b;
4512 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4516 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4520 pad_heap (MonoDynamicStream *sh)
4522 if (sh->index & 3) {
4523 int sz = 4 - (sh->index & 3);
4524 memset (sh->data + sh->index, 0, sz);
4531 MonoDynamicStream *stream;
4535 * build_compressed_metadata() fills in the blob of data that represents the
4536 * raw metadata as it will be saved in the PE file. The five streams are output
4537 * and the metadata tables are comnpressed from the guint32 array representation,
4538 * to the compressed on-disk format.
4541 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4543 MonoDynamicTable *table;
4545 guint64 valid_mask = 0;
4546 guint64 sorted_mask;
4547 guint32 heapt_size = 0;
4548 guint32 meta_size = 256; /* allow for header and other stuff */
4549 guint32 table_offset;
4550 guint32 ntables = 0;
4556 struct StreamDesc stream_desc [5];
4558 mono_error_init (error);
4560 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4561 for (i = 0; i < assembly->gen_params->len; i++) {
4562 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4563 if (!write_generic_param_entry (assembly, entry, error))
4567 stream_desc [0].name = "#~";
4568 stream_desc [0].stream = &assembly->tstream;
4569 stream_desc [1].name = "#Strings";
4570 stream_desc [1].stream = &assembly->sheap;
4571 stream_desc [2].name = "#US";
4572 stream_desc [2].stream = &assembly->us;
4573 stream_desc [3].name = "#Blob";
4574 stream_desc [3].stream = &assembly->blob;
4575 stream_desc [4].name = "#GUID";
4576 stream_desc [4].stream = &assembly->guid;
4578 /* tables that are sorted */
4579 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4580 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4581 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4582 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4583 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4584 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4585 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4587 /* Compute table sizes */
4588 /* the MonoImage has already been created in mono_image_basic_init() */
4589 meta = &assembly->image;
4591 /* sizes should be multiple of 4 */
4592 pad_heap (&assembly->blob);
4593 pad_heap (&assembly->guid);
4594 pad_heap (&assembly->sheap);
4595 pad_heap (&assembly->us);
4597 /* Setup the info used by compute_sizes () */
4598 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4599 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4600 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4602 meta_size += assembly->blob.index;
4603 meta_size += assembly->guid.index;
4604 meta_size += assembly->sheap.index;
4605 meta_size += assembly->us.index;
4607 for (i=0; i < MONO_TABLE_NUM; ++i)
4608 meta->tables [i].rows = assembly->tables [i].rows;
4610 for (i = 0; i < MONO_TABLE_NUM; i++){
4611 if (meta->tables [i].rows == 0)
4613 valid_mask |= (guint64)1 << i;
4615 meta->tables [i].row_size = mono_metadata_compute_size (
4616 meta, i, &meta->tables [i].size_bitfield);
4617 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4619 heapt_size += 24; /* #~ header size */
4620 heapt_size += ntables * 4;
4621 /* make multiple of 4 */
4624 meta_size += heapt_size;
4625 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4626 p = (unsigned char*)meta->raw_metadata;
4627 /* the metadata signature */
4628 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4629 /* version numbers and 4 bytes reserved */
4630 int16val = (guint16*)p;
4631 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4632 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4634 /* version string */
4635 int32val = (guint32*)p;
4636 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4638 memcpy (p, meta->version, strlen (meta->version));
4639 p += GUINT32_FROM_LE (*int32val);
4640 align_pointer (meta->raw_metadata, p);
4641 int16val = (guint16*)p;
4642 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4643 *int16val = GUINT16_TO_LE (5); /* number of streams */
4647 * write the stream info.
4649 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4650 table_offset += 3; table_offset &= ~3;
4652 assembly->tstream.index = heapt_size;
4653 for (i = 0; i < 5; ++i) {
4654 int32val = (guint32*)p;
4655 stream_desc [i].stream->offset = table_offset;
4656 *int32val++ = GUINT32_TO_LE (table_offset);
4657 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4658 table_offset += GUINT32_FROM_LE (*int32val);
4659 table_offset += 3; table_offset &= ~3;
4661 strcpy ((char*)p, stream_desc [i].name);
4662 p += strlen (stream_desc [i].name) + 1;
4663 align_pointer (meta->raw_metadata, p);
4666 * now copy the data, the table stream header and contents goes first.
4668 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4669 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4670 int32val = (guint32*)p;
4671 *int32val = GUINT32_TO_LE (0); /* reserved */
4674 *p++ = 2; /* version */
4677 if (meta->idx_string_wide)
4679 if (meta->idx_guid_wide)
4681 if (meta->idx_blob_wide)
4684 *p++ = 1; /* reserved */
4685 int64val = (guint64*)p;
4686 *int64val++ = GUINT64_TO_LE (valid_mask);
4687 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4689 int32val = (guint32*)p;
4690 for (i = 0; i < MONO_TABLE_NUM; i++){
4691 if (meta->tables [i].rows == 0)
4693 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4695 p = (unsigned char*)int32val;
4697 /* sort the tables that still need sorting */
4698 table = &assembly->tables [MONO_TABLE_CONSTANT];
4700 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4701 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4703 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4704 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4706 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4707 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4709 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4710 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4712 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4713 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4714 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4716 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4717 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4719 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4721 /* compress the tables */
4722 for (i = 0; i < MONO_TABLE_NUM; i++){
4725 guint32 bitfield = meta->tables [i].size_bitfield;
4726 if (!meta->tables [i].rows)
4728 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4729 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4730 meta->tables [i].base = (char*)p;
4731 for (row = 1; row <= meta->tables [i].rows; ++row) {
4732 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4733 for (col = 0; col < assembly->tables [i].columns; ++col) {
4734 switch (mono_metadata_table_size (bitfield, col)) {
4736 *p++ = values [col];
4739 *p++ = values [col] & 0xff;
4740 *p++ = (values [col] >> 8) & 0xff;
4743 *p++ = values [col] & 0xff;
4744 *p++ = (values [col] >> 8) & 0xff;
4745 *p++ = (values [col] >> 16) & 0xff;
4746 *p++ = (values [col] >> 24) & 0xff;
4749 g_assert_not_reached ();
4753 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4756 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4757 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4758 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4759 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4760 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4762 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4768 * Some tables in metadata need to be sorted according to some criteria, but
4769 * when methods and fields are first created with reflection, they may be assigned a token
4770 * that doesn't correspond to the final token they will get assigned after the sorting.
4771 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4772 * with the reflection objects that represent them. Once all the tables are set up, the
4773 * reflection objects will contains the correct table index. fixup_method() will fixup the
4774 * tokens for the method with ILGenerator @ilgen.
4777 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4779 guint32 code_idx = GPOINTER_TO_UINT (value);
4780 MonoReflectionILTokenInfo *iltoken;
4781 MonoReflectionFieldBuilder *field;
4782 MonoReflectionCtorBuilder *ctor;
4783 MonoReflectionMethodBuilder *method;
4784 MonoReflectionTypeBuilder *tb;
4785 MonoReflectionArrayMethod *am;
4787 unsigned char *target;
4789 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4790 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4791 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4792 switch (target [3]) {
4793 case MONO_TABLE_FIELD:
4794 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4795 field = (MonoReflectionFieldBuilder *)iltoken->member;
4796 idx = field->table_idx;
4797 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4798 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4799 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4801 g_assert_not_reached ();
4804 case MONO_TABLE_METHOD:
4805 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4806 method = (MonoReflectionMethodBuilder *)iltoken->member;
4807 idx = method->table_idx;
4808 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4809 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4810 idx = ctor->table_idx;
4811 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4812 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4813 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4814 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4816 g_assert_not_reached ();
4819 case MONO_TABLE_TYPEDEF:
4820 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4821 g_assert_not_reached ();
4822 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4823 idx = tb->table_idx;
4825 case MONO_TABLE_MEMBERREF:
4826 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4827 am = (MonoReflectionArrayMethod*)iltoken->member;
4828 idx = am->table_idx;
4829 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4830 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4831 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4832 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4833 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4834 g_assert (m->klass->generic_class || m->klass->generic_container);
4836 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4838 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4839 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4840 g_assert (is_field_on_inst (f));
4842 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4843 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4845 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4847 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4849 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4852 g_assert_not_reached ();
4855 case MONO_TABLE_METHODSPEC:
4856 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4857 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4858 g_assert (mono_method_signature (m)->generic_param_count);
4860 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4862 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4865 g_assert_not_reached ();
4869 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4871 target [0] = idx & 0xff;
4872 target [1] = (idx >> 8) & 0xff;
4873 target [2] = (idx >> 16) & 0xff;
4880 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4881 * value is not known when the table is emitted.
4884 fixup_cattrs (MonoDynamicImage *assembly)
4886 MonoDynamicTable *table;
4888 guint32 type, i, idx, token;
4891 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4893 for (i = 0; i < table->rows; ++i) {
4894 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4896 type = values [MONO_CUSTOM_ATTR_TYPE];
4897 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4898 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4899 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4900 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4903 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4904 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4905 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4906 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4907 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4908 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4909 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4910 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4917 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4919 MonoDynamicTable *table;
4922 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4924 alloc_table (table, table->rows);
4925 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4926 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4927 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4928 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4929 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4934 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4936 MonoDynamicTable *table;
4940 char *b = blob_size;
4942 guint32 idx, offset;
4944 if (rsrc->filename) {
4945 name = mono_string_to_utf8 (rsrc->filename);
4946 sname = g_path_get_basename (name);
4948 table = &assembly->tables [MONO_TABLE_FILE];
4950 alloc_table (table, table->rows);
4951 values = table->values + table->next_idx * MONO_FILE_SIZE;
4952 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4953 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4956 mono_sha1_get_digest_from_file (name, hash);
4957 mono_metadata_encode_value (20, b, &b);
4958 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4959 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4961 idx = table->next_idx++;
4963 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4969 data = mono_array_addr (rsrc->data, char, 0);
4970 len = mono_array_length (rsrc->data);
4976 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4977 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4978 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4979 mono_image_add_stream_data (&assembly->resources, data, len);
4983 * The entry should be emitted into the MANIFESTRESOURCE table of
4984 * the main module, but that needs to reference the FILE table
4985 * which isn't emitted yet.
4992 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4996 set_version_from_string (MonoString *version, guint32 *values)
4998 gchar *ver, *p, *str;
5001 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5002 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5003 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5004 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5007 ver = str = mono_string_to_utf8 (version);
5008 for (i = 0; i < 4; ++i) {
5009 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5015 /* handle Revision and Build */
5025 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5029 char *b = blob_size;
5034 len = mono_array_length (pkey);
5035 mono_metadata_encode_value (len, b, &b);
5036 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5037 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5039 assembly->public_key = (guint8 *)g_malloc (len);
5040 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5041 assembly->public_key_len = len;
5043 /* Special case: check for ECMA key (16 bytes) */
5044 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5045 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5046 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5047 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5048 /* minimum key size (in 2.0) is 384 bits */
5049 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5051 /* FIXME - verifier */
5052 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5053 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5055 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5061 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5063 MonoDynamicTable *table;
5064 MonoDynamicImage *assembly;
5065 MonoReflectionAssemblyBuilder *assemblyb;
5069 guint32 module_index;
5071 assemblyb = moduleb->assemblyb;
5072 assembly = moduleb->dynamic_image;
5073 domain = mono_object_domain (assemblyb);
5075 /* Emit ASSEMBLY table */
5076 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5077 alloc_table (table, 1);
5078 values = table->values + MONO_ASSEMBLY_SIZE;
5079 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5080 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5081 if (assemblyb->culture) {
5082 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5084 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5086 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5087 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5088 set_version_from_string (assemblyb->version, values);
5090 /* Emit FILE + EXPORTED_TYPE table */
5092 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5094 MonoReflectionModuleBuilder *file_module =
5095 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5096 if (file_module != moduleb) {
5097 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5099 if (file_module->types) {
5100 for (j = 0; j < file_module->num_types; ++j) {
5101 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5102 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5107 if (assemblyb->loaded_modules) {
5108 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5109 MonoReflectionModule *file_module =
5110 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5111 mono_image_fill_file_table (domain, file_module, assembly);
5113 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5116 if (assemblyb->type_forwarders)
5117 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5119 /* Emit MANIFESTRESOURCE table */
5121 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5123 MonoReflectionModuleBuilder *file_module =
5124 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5125 /* The table for the main module is emitted later */
5126 if (file_module != moduleb) {
5128 if (file_module->resources) {
5129 int len = mono_array_length (file_module->resources);
5130 for (j = 0; j < len; ++j) {
5131 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5132 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5139 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5142 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5143 * for the modulebuilder @moduleb.
5144 * At the end of the process, method and field tokens are fixed up and the
5145 * on-disk compressed metadata representation is created.
5146 * Return TRUE on success, or FALSE on failure and sets @error
5149 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5151 MonoDynamicTable *table;
5152 MonoDynamicImage *assembly;
5153 MonoReflectionAssemblyBuilder *assemblyb;
5159 mono_error_init (error);
5161 assemblyb = moduleb->assemblyb;
5162 assembly = moduleb->dynamic_image;
5163 domain = mono_object_domain (assemblyb);
5165 if (assembly->text_rva)
5168 assembly->text_rva = START_TEXT_RVA;
5170 if (moduleb->is_main) {
5171 mono_image_emit_manifest (moduleb);
5174 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5175 table->rows = 1; /* .<Module> */
5177 alloc_table (table, table->rows);
5179 * Set the first entry.
5181 values = table->values + table->columns;
5182 values [MONO_TYPEDEF_FLAGS] = 0;
5183 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5184 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5185 values [MONO_TYPEDEF_EXTENDS] = 0;
5186 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5187 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5190 * handle global methods
5191 * FIXME: test what to do when global methods are defined in multiple modules.
5193 if (moduleb->global_methods) {
5194 table = &assembly->tables [MONO_TABLE_METHOD];
5195 table->rows += mono_array_length (moduleb->global_methods);
5196 alloc_table (table, table->rows);
5197 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5198 if (!mono_image_get_method_info (
5199 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5203 if (moduleb->global_fields) {
5204 table = &assembly->tables [MONO_TABLE_FIELD];
5205 table->rows += mono_array_length (moduleb->global_fields);
5206 alloc_table (table, table->rows);
5207 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5208 mono_image_get_field_info (
5209 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5216 table = &assembly->tables [MONO_TABLE_MODULE];
5217 alloc_table (table, 1);
5218 mono_image_fill_module_table (domain, moduleb, assembly);
5220 /* Collect all types into a list sorted by their table_idx */
5221 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5224 for (i = 0; i < moduleb->num_types; ++i) {
5225 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5226 collect_types (&types, type);
5229 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5230 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5231 table->rows += mono_ptr_array_size (types);
5232 alloc_table (table, table->rows);
5235 * Emit type names + namespaces at one place inside the string heap,
5236 * so load_class_names () needs to touch fewer pages.
5238 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5239 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5240 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5242 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5243 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5244 string_heap_insert_mstring (&assembly->sheap, tb->name);
5247 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5248 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5249 if (!mono_image_get_type_info (domain, type, assembly, error))
5254 * table->rows is already set above and in mono_image_fill_module_table.
5256 /* add all the custom attributes at the end, once all the indexes are stable */
5257 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5260 /* CAS assembly permissions */
5261 if (assemblyb->permissions_minimum)
5262 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5263 if (assemblyb->permissions_optional)
5264 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5265 if (assemblyb->permissions_refused)
5266 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5268 if (!module_add_cattrs (assembly, moduleb, error))
5272 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5274 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5275 * the final tokens and don't need another fixup pass. */
5277 if (moduleb->global_methods) {
5278 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5279 MonoReflectionMethodBuilder *mb = mono_array_get (
5280 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5281 if (!mono_image_add_methodimpl (assembly, mb, error))
5286 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5287 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5288 if (type->methods) {
5289 for (j = 0; j < type->num_methods; ++j) {
5290 MonoReflectionMethodBuilder *mb = mono_array_get (
5291 type->methods, MonoReflectionMethodBuilder*, j);
5293 if (!mono_image_add_methodimpl (assembly, mb, error))
5299 fixup_cattrs (assembly);
5302 mono_ptr_array_destroy (types);
5305 return mono_error_ok (error);
5308 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5311 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5313 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5316 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5320 guint32 import_lookup_table;
5324 guint32 import_address_table_rva;
5332 #ifndef DISABLE_REFLECTION_EMIT
5335 * mono_image_insert_string:
5336 * @module: module builder object
5339 * Insert @str into the user string stream of @module.
5342 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5344 MonoDynamicImage *assembly;
5349 if (!module->dynamic_image)
5350 mono_image_module_basic_init (module);
5352 assembly = module->dynamic_image;
5354 if (assembly->save) {
5355 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5356 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5357 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5359 char *swapped = g_malloc (2 * mono_string_length (str));
5360 const char *p = (const char*)mono_string_chars (str);
5362 swap_with_size (swapped, p, 2, mono_string_length (str));
5363 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5367 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5369 mono_image_add_stream_data (&assembly->us, "", 1);
5371 idx = assembly->us.index ++;
5374 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5376 return MONO_TOKEN_STRING | idx;
5380 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5384 MonoMethodSignature *sig;
5386 mono_error_init (error);
5388 klass = obj->vtable->klass;
5389 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5390 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5391 MonoMethodSignature *old;
5392 guint32 sig_token, parent;
5395 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5397 nargs = mono_array_length (opt_param_types);
5398 old = mono_method_signature (method);
5399 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5401 sig->hasthis = old->hasthis;
5402 sig->explicit_this = old->explicit_this;
5403 sig->call_convention = old->call_convention;
5404 sig->generic_param_count = old->generic_param_count;
5405 sig->param_count = old->param_count + nargs;
5406 sig->sentinelpos = old->param_count;
5407 sig->ret = old->ret;
5409 for (i = 0; i < old->param_count; i++)
5410 sig->params [i] = old->params [i];
5412 for (i = 0; i < nargs; i++) {
5413 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5414 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5415 if (!is_ok (error)) goto fail;
5418 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5419 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5420 parent >>= MONO_TYPEDEFORREF_BITS;
5422 parent <<= MONO_MEMBERREF_PARENT_BITS;
5423 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5425 sig_token = method_encode_signature (assembly, sig);
5426 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5427 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5428 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5429 ReflectionMethodBuilder rmb;
5430 guint32 parent, sig_token;
5431 int nopt_args, nparams, ngparams, i;
5433 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5436 rmb.opt_types = opt_param_types;
5437 nopt_args = mono_array_length (opt_param_types);
5439 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5440 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5441 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5443 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5444 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5445 sig->call_convention = rmb.call_conv;
5446 sig->generic_param_count = ngparams;
5447 sig->param_count = nparams + nopt_args;
5448 sig->sentinelpos = nparams;
5449 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5450 if (!is_ok (error)) goto fail;
5452 for (i = 0; i < nparams; i++) {
5453 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5454 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5455 if (!is_ok (error)) goto fail;
5458 for (i = 0; i < nopt_args; i++) {
5459 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5460 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5461 if (!is_ok (error)) goto fail;
5464 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5468 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5469 if (!mono_error_ok (error))
5471 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5473 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5474 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5476 char *name = mono_string_to_utf8 (rmb.name);
5477 token = mono_image_get_varargs_method_token (
5478 assembly, parent, name, sig_token);
5481 g_error ("requested method token for %s\n", klass->name);
5484 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5485 register_dyn_token (assembly, token, obj);
5488 g_assert (!mono_error_ok (error));
5493 * mono_image_create_token:
5494 * @assembly: a dynamic assembly
5496 * @register_token: Whenever to register the token in the assembly->tokens hash.
5498 * Get a token to insert in the IL code stream for the given MemberInfo.
5499 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5500 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5504 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5505 gboolean create_open_instance, gboolean register_token,
5511 mono_error_init (error);
5513 klass = obj->vtable->klass;
5515 /* Check for user defined reflection objects */
5516 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5517 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5518 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5522 if (strcmp (klass->name, "MethodBuilder") == 0) {
5523 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5524 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5526 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5527 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5529 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5530 if (!mono_error_ok (error))
5533 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5534 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5535 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5536 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5538 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5539 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5541 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5542 if (!mono_error_ok (error))
5545 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5546 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5547 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5548 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5549 if (tb->generic_params) {
5550 token = mono_image_get_generic_field_token (assembly, fb, error);
5551 return_val_if_nok (error, 0);
5553 if (tb->module->dynamic_image == assembly) {
5554 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5556 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5559 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5560 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5561 if (create_open_instance && tb->generic_params) {
5563 init_type_builder_generics (obj);
5564 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5565 return_val_if_nok (error, 0);
5566 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5567 token = mono_metadata_token_from_dor (token);
5568 } else if (tb->module->dynamic_image == assembly) {
5569 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5572 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5573 return_val_if_nok (error, 0);
5574 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5576 } else if (strcmp (klass->name, "MonoType") == 0) {
5577 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5578 return_val_if_nok (error, 0);
5579 MonoClass *mc = mono_class_from_mono_type (type);
5580 token = mono_metadata_token_from_dor (
5581 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5582 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5583 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5584 return_val_if_nok (error, 0);
5585 token = mono_metadata_token_from_dor (
5586 mono_image_typedef_or_ref (assembly, type));
5587 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5588 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5589 return_val_if_nok (error, 0);
5590 token = mono_metadata_token_from_dor (
5591 mono_image_typedef_or_ref (assembly, type));
5592 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5593 strcmp (klass->name, "MonoMethod") == 0 ||
5594 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5595 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5596 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5597 if (m->method->is_inflated) {
5598 if (create_open_instance)
5599 token = mono_image_get_methodspec_token (assembly, m->method);
5601 token = mono_image_get_inflated_method_token (assembly, m->method);
5602 } else if ((m->method->klass->image == &assembly->image) &&
5603 !m->method->klass->generic_class) {
5604 static guint32 method_table_idx = 0xffffff;
5605 if (m->method->klass->wastypebuilder) {
5606 /* we use the same token as the one that was assigned
5607 * to the Methodbuilder.
5608 * FIXME: do the equivalent for Fields.
5610 token = m->method->token;
5613 * Each token should have a unique index, but the indexes are
5614 * assigned by managed code, so we don't know about them. An
5615 * easy solution is to count backwards...
5617 method_table_idx --;
5618 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5621 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5623 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5624 } else if (strcmp (klass->name, "MonoField") == 0) {
5625 MonoReflectionField *f = (MonoReflectionField *)obj;
5626 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5627 static guint32 field_table_idx = 0xffffff;
5629 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5631 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5633 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5634 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5635 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5636 token = mono_image_get_array_token (assembly, m);
5637 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5638 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5639 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5640 return_val_if_nok (error, 0);
5641 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5642 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5643 return_val_if_nok (error, 0);
5644 token = mono_metadata_token_from_dor (
5645 mono_image_typedef_or_ref (assembly, type));
5646 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5647 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5648 token = mono_image_get_field_on_inst_token (assembly, f, error);
5649 return_val_if_nok (error, 0);
5650 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5651 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5652 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5653 if (!mono_error_ok (error))
5655 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5656 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5657 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5658 if (!mono_error_ok (error))
5660 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5661 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5662 return_val_if_nok (error, 0);
5663 token = mono_metadata_token_from_dor (
5664 mono_image_typedef_or_ref (assembly, type));
5666 g_error ("requested token for %s\n", klass->name);
5670 mono_image_register_token (assembly, token, obj);
5676 * mono_image_register_token:
5678 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5679 * the Module.ResolveXXXToken () methods to work.
5682 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5686 dynamic_image_lock (assembly);
5687 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5689 /* There could be multiple MethodInfo objects with the same token */
5690 //g_assert (prev == obj);
5692 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5694 dynamic_image_unlock (assembly);
5697 static MonoDynamicImage*
5698 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5700 static const guchar entrycode [16] = {0xff, 0x25, 0};
5701 MonoDynamicImage *image;
5704 const char *version;
5706 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5707 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5709 version = mono_get_runtime_info ()->runtime_version;
5712 /* The MonoGHashTable's need GC tracking */
5713 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5715 image = g_new0 (MonoDynamicImage, 1);
5718 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5720 /*g_print ("created image %p\n", image);*/
5721 /* keep in sync with image.c */
5722 image->image.name = assembly_name;
5723 image->image.assembly_name = image->image.name; /* they may be different */
5724 image->image.module_name = module_name;
5725 image->image.version = g_strdup (version);
5726 image->image.md_version_major = 1;
5727 image->image.md_version_minor = 1;
5728 image->image.dynamic = TRUE;
5730 image->image.references = g_new0 (MonoAssembly*, 1);
5731 image->image.references [0] = NULL;
5733 mono_image_init (&image->image);
5735 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");
5736 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5737 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5738 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5739 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5740 image->handleref = g_hash_table_new (NULL, NULL);
5741 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");
5742 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5743 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");
5744 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");
5745 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5746 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5747 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5748 image->gen_params = g_ptr_array_new ();
5749 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5751 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5752 string_heap_init (&image->sheap);
5753 mono_image_add_stream_data (&image->us, "", 1);
5754 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5755 /* import tables... */
5756 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5757 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5758 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5759 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5760 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5761 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5762 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5763 stream_data_align (&image->code);
5765 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5767 for (i=0; i < MONO_TABLE_NUM; ++i) {
5768 image->tables [i].next_idx = 1;
5769 image->tables [i].columns = table_sizes [i];
5772 image->image.assembly = (MonoAssembly*)assembly;
5773 image->run = assembly->run;
5774 image->save = assembly->save;
5775 image->pe_kind = 0x1; /* ILOnly */
5776 image->machine = 0x14c; /* I386 */
5778 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5780 dynamic_images_lock ();
5782 if (!dynamic_images)
5783 dynamic_images = g_ptr_array_new ();
5785 g_ptr_array_add (dynamic_images, image);
5787 dynamic_images_unlock ();
5794 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5800 release_hashtable (MonoGHashTable **hash)
5803 mono_g_hash_table_destroy (*hash);
5809 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5811 release_hashtable (&image->token_fixups);
5812 release_hashtable (&image->handleref_managed);
5813 release_hashtable (&image->tokens);
5814 release_hashtable (&image->remapped_tokens);
5815 release_hashtable (&image->generic_def_objects);
5816 release_hashtable (&image->methodspec);
5819 // Free dynamic image pass one: Free resources but not image itself
5821 mono_dynamic_image_free (MonoDynamicImage *image)
5823 MonoDynamicImage *di = image;
5828 mono_g_hash_table_destroy (di->methodspec);
5830 g_hash_table_destroy (di->typespec);
5832 g_hash_table_destroy (di->typeref);
5834 g_hash_table_destroy (di->handleref);
5835 if (di->handleref_managed)
5836 mono_g_hash_table_destroy (di->handleref_managed);
5838 mono_g_hash_table_destroy (di->tokens);
5839 if (di->remapped_tokens)
5840 mono_g_hash_table_destroy (di->remapped_tokens);
5841 if (di->generic_def_objects)
5842 mono_g_hash_table_destroy (di->generic_def_objects);
5843 if (di->blob_cache) {
5844 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5845 g_hash_table_destroy (di->blob_cache);
5847 if (di->standalonesig_cache)
5848 g_hash_table_destroy (di->standalonesig_cache);
5849 for (list = di->array_methods; list; list = list->next) {
5850 ArrayMethod *am = (ArrayMethod *)list->data;
5855 g_list_free (di->array_methods);
5856 if (di->gen_params) {
5857 for (i = 0; i < di->gen_params->len; i++) {
5858 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5859 mono_gc_deregister_root ((char*) &entry->gparam);
5862 g_ptr_array_free (di->gen_params, TRUE);
5864 if (di->token_fixups)
5865 mono_g_hash_table_destroy (di->token_fixups);
5866 if (di->method_to_table_idx)
5867 g_hash_table_destroy (di->method_to_table_idx);
5868 if (di->field_to_table_idx)
5869 g_hash_table_destroy (di->field_to_table_idx);
5870 if (di->method_aux_hash)
5871 g_hash_table_destroy (di->method_aux_hash);
5872 if (di->vararg_aux_hash)
5873 g_hash_table_destroy (di->vararg_aux_hash);
5874 g_free (di->strong_name);
5875 g_free (di->win32_res);
5877 g_free (di->public_key);
5879 /*g_print ("string heap destroy for image %p\n", di);*/
5880 mono_dynamic_stream_reset (&di->sheap);
5881 mono_dynamic_stream_reset (&di->code);
5882 mono_dynamic_stream_reset (&di->resources);
5883 mono_dynamic_stream_reset (&di->us);
5884 mono_dynamic_stream_reset (&di->blob);
5885 mono_dynamic_stream_reset (&di->tstream);
5886 mono_dynamic_stream_reset (&di->guid);
5887 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5888 g_free (di->tables [i].values);
5891 dynamic_images_lock ();
5894 g_ptr_array_remove (dynamic_images, di);
5896 dynamic_images_unlock ();
5899 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5901 mono_dynamic_image_free_image (MonoDynamicImage *image)
5903 /* See create_dynamic_mono_image () */
5905 /* Allocated using GC_MALLOC */
5911 #ifndef DISABLE_REFLECTION_EMIT
5914 * mono_image_basic_init:
5915 * @assembly: an assembly builder object
5917 * Create the MonoImage that represents the assembly builder and setup some
5918 * of the helper hash table and the basic metadata streams.
5921 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5923 MonoDynamicAssembly *assembly;
5924 MonoDynamicImage *image;
5925 MonoDomain *domain = mono_object_domain (assemblyb);
5927 if (assemblyb->dynamic_assembly)
5931 /* assembly->assembly.image might be GC allocated */
5932 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5934 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5937 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5939 assembly->assembly.ref_count = 1;
5940 assembly->assembly.dynamic = TRUE;
5941 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5942 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5943 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5944 if (assemblyb->culture)
5945 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5947 assembly->assembly.aname.culture = g_strdup ("");
5949 if (assemblyb->version) {
5950 char *vstr = mono_string_to_utf8 (assemblyb->version);
5951 char **version = g_strsplit (vstr, ".", 4);
5952 char **parts = version;
5953 assembly->assembly.aname.major = atoi (*parts++);
5954 assembly->assembly.aname.minor = atoi (*parts++);
5955 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5956 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5958 g_strfreev (version);
5961 assembly->assembly.aname.major = 0;
5962 assembly->assembly.aname.minor = 0;
5963 assembly->assembly.aname.build = 0;
5964 assembly->assembly.aname.revision = 0;
5967 assembly->run = assemblyb->access != 2;
5968 assembly->save = assemblyb->access != 1;
5969 assembly->domain = domain;
5971 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5972 image->initial_image = TRUE;
5973 assembly->assembly.aname.name = image->image.name;
5974 assembly->assembly.image = &image->image;
5975 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5976 /* -1 to correct for the trailing NULL byte */
5977 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5978 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5980 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5983 mono_domain_assemblies_lock (domain);
5984 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5985 mono_domain_assemblies_unlock (domain);
5987 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5989 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5991 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5994 #endif /* !DISABLE_REFLECTION_EMIT */
5996 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5999 calc_section_size (MonoDynamicImage *assembly)
6003 /* alignment constraints */
6004 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6005 g_assert ((assembly->code.index % 4) == 0);
6006 assembly->meta_size += 3;
6007 assembly->meta_size &= ~3;
6008 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6009 g_assert ((assembly->resources.index % 4) == 0);
6011 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6012 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6015 if (assembly->win32_res) {
6016 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6018 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6019 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6023 assembly->sections [MONO_SECTION_RELOC].size = 12;
6024 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6034 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6038 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6040 ResTreeNode *t1 = (ResTreeNode*)a;
6041 ResTreeNode *t2 = (ResTreeNode*)b;
6043 return t1->id - t2->id;
6047 * resource_tree_create:
6049 * Organize the resources into a resource tree.
6051 static ResTreeNode *
6052 resource_tree_create (MonoArray *win32_resources)
6054 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6058 tree = g_new0 (ResTreeNode, 1);
6060 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6061 MonoReflectionWin32Resource *win32_res =
6062 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6066 /* FIXME: BUG: this stores managed references in unmanaged memory */
6067 lang_node = g_new0 (ResTreeNode, 1);
6068 lang_node->id = win32_res->lang_id;
6069 lang_node->win32_res = win32_res;
6071 /* Create type node if neccesary */
6073 for (l = tree->children; l; l = l->next)
6074 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6075 type_node = (ResTreeNode*)l->data;
6080 type_node = g_new0 (ResTreeNode, 1);
6081 type_node->id = win32_res->res_type;
6084 * The resource types have to be sorted otherwise
6085 * Windows Explorer can't display the version information.
6087 tree->children = g_slist_insert_sorted (tree->children,
6088 type_node, resource_tree_compare_by_id);
6091 /* Create res node if neccesary */
6093 for (l = type_node->children; l; l = l->next)
6094 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6095 res_node = (ResTreeNode*)l->data;
6100 res_node = g_new0 (ResTreeNode, 1);
6101 res_node->id = win32_res->res_id;
6102 type_node->children = g_slist_append (type_node->children, res_node);
6105 res_node->children = g_slist_append (res_node->children, lang_node);
6112 * resource_tree_encode:
6114 * Encode the resource tree into the format used in the PE file.
6117 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6120 MonoPEResourceDir dir;
6121 MonoPEResourceDirEntry dir_entry;
6122 MonoPEResourceDataEntry data_entry;
6124 guint32 res_id_entries;
6127 * For the format of the resource directory, see the article
6128 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6132 memset (&dir, 0, sizeof (dir));
6133 memset (&dir_entry, 0, sizeof (dir_entry));
6134 memset (&data_entry, 0, sizeof (data_entry));
6136 g_assert (sizeof (dir) == 16);
6137 g_assert (sizeof (dir_entry) == 8);
6138 g_assert (sizeof (data_entry) == 16);
6140 node->offset = p - begin;
6142 /* IMAGE_RESOURCE_DIRECTORY */
6143 res_id_entries = g_slist_length (node->children);
6144 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6146 memcpy (p, &dir, sizeof (dir));
6149 /* Reserve space for entries */
6151 p += sizeof (dir_entry) * res_id_entries;
6153 /* Write children */
6154 for (l = node->children; l; l = l->next) {
6155 ResTreeNode *child = (ResTreeNode*)l->data;
6157 if (child->win32_res) {
6160 child->offset = p - begin;
6162 /* IMAGE_RESOURCE_DATA_ENTRY */
6163 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6164 size = mono_array_length (child->win32_res->res_data);
6165 data_entry.rde_size = GUINT32_TO_LE (size);
6167 memcpy (p, &data_entry, sizeof (data_entry));
6168 p += sizeof (data_entry);
6170 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6173 resource_tree_encode (child, begin, p, &p);
6177 /* IMAGE_RESOURCE_ENTRY */
6178 for (l = node->children; l; l = l->next) {
6179 ResTreeNode *child = (ResTreeNode*)l->data;
6181 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6182 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6184 memcpy (entries, &dir_entry, sizeof (dir_entry));
6185 entries += sizeof (dir_entry);
6192 resource_tree_free (ResTreeNode * node)
6195 for (list = node->children; list; list = list->next)
6196 resource_tree_free ((ResTreeNode*)list->data);
6197 g_slist_free(node->children);
6202 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6207 MonoReflectionWin32Resource *win32_res;
6210 if (!assemblyb->win32_resources)
6214 * Resources are stored in a three level tree inside the PE file.
6215 * - level one contains a node for each type of resource
6216 * - level two contains a node for each resource
6217 * - level three contains a node for each instance of a resource for a
6218 * specific language.
6221 tree = resource_tree_create (assemblyb->win32_resources);
6223 /* Estimate the size of the encoded tree */
6225 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6226 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6227 size += mono_array_length (win32_res->res_data);
6229 /* Directory structure */
6230 size += mono_array_length (assemblyb->win32_resources) * 256;
6231 p = buf = (char *)g_malloc (size);
6233 resource_tree_encode (tree, p, p, &p);
6235 g_assert (p - buf <= size);
6237 assembly->win32_res = (char *)g_malloc (p - buf);
6238 assembly->win32_res_size = p - buf;
6239 memcpy (assembly->win32_res, buf, p - buf);
6242 resource_tree_free (tree);
6246 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6248 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6251 p += sizeof (MonoPEResourceDir);
6252 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6253 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6254 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6255 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6256 fixup_resource_directory (res_section, child, rva);
6258 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6259 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6262 p += sizeof (MonoPEResourceDirEntry);
6267 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6270 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6271 g_error ("WriteFile returned %d\n", GetLastError ());
6275 * mono_image_create_pefile:
6276 * @mb: a module builder object
6278 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6279 * assembly->pefile where it can be easily retrieved later in chunks.
6282 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6284 MonoMSDOSHeader *msdos;
6285 MonoDotNetHeader *header;
6286 MonoSectionTable *section;
6287 MonoCLIHeader *cli_header;
6288 guint32 size, image_size, virtual_base, text_offset;
6289 guint32 header_start, section_start, file_offset, virtual_offset;
6290 MonoDynamicImage *assembly;
6291 MonoReflectionAssemblyBuilder *assemblyb;
6292 MonoDynamicStream pefile_stream = {0};
6293 MonoDynamicStream *pefile = &pefile_stream;
6295 guint32 *rva, value;
6297 static const unsigned char msheader[] = {
6298 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6299 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6302 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6303 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6304 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6305 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6308 mono_error_init (error);
6310 assemblyb = mb->assemblyb;
6312 mono_image_basic_init (assemblyb);
6313 assembly = mb->dynamic_image;
6315 assembly->pe_kind = assemblyb->pe_kind;
6316 assembly->machine = assemblyb->machine;
6317 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6318 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6320 if (!mono_image_build_metadata (mb, error))
6324 if (mb->is_main && assemblyb->resources) {
6325 int len = mono_array_length (assemblyb->resources);
6326 for (i = 0; i < len; ++i)
6327 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6330 if (mb->resources) {
6331 int len = mono_array_length (mb->resources);
6332 for (i = 0; i < len; ++i)
6333 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6336 if (!build_compressed_metadata (assembly, error))
6340 assembly_add_win32_resources (assembly, assemblyb);
6342 nsections = calc_section_size (assembly);
6344 /* The DOS header and stub */
6345 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6346 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6348 /* the dotnet header */
6349 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6351 /* the section tables */
6352 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6354 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6355 virtual_offset = VIRT_ALIGN;
6358 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6359 if (!assembly->sections [i].size)
6362 file_offset += FILE_ALIGN - 1;
6363 file_offset &= ~(FILE_ALIGN - 1);
6364 virtual_offset += VIRT_ALIGN - 1;
6365 virtual_offset &= ~(VIRT_ALIGN - 1);
6367 assembly->sections [i].offset = file_offset;
6368 assembly->sections [i].rva = virtual_offset;
6370 file_offset += assembly->sections [i].size;
6371 virtual_offset += assembly->sections [i].size;
6372 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6375 file_offset += FILE_ALIGN - 1;
6376 file_offset &= ~(FILE_ALIGN - 1);
6378 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6380 /* back-patch info */
6381 msdos = (MonoMSDOSHeader*)pefile->data;
6382 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6384 header = (MonoDotNetHeader*)(pefile->data + header_start);
6385 header->pesig [0] = 'P';
6386 header->pesig [1] = 'E';
6388 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6389 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6390 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6391 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6392 if (assemblyb->pekind == 1) {
6394 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6397 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6400 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6402 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6403 header->pe.pe_major = 6;
6404 header->pe.pe_minor = 0;
6405 size = assembly->sections [MONO_SECTION_TEXT].size;
6406 size += FILE_ALIGN - 1;
6407 size &= ~(FILE_ALIGN - 1);
6408 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6409 size = assembly->sections [MONO_SECTION_RSRC].size;
6410 size += FILE_ALIGN - 1;
6411 size &= ~(FILE_ALIGN - 1);
6412 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6413 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6414 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6415 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6416 /* pe_rva_entry_point always at the beginning of the text section */
6417 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6419 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6420 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6421 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6422 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6423 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6424 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6425 size = section_start;
6426 size += FILE_ALIGN - 1;
6427 size &= ~(FILE_ALIGN - 1);
6428 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6430 size += VIRT_ALIGN - 1;
6431 size &= ~(VIRT_ALIGN - 1);
6432 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6435 // Translate the PEFileKind value to the value expected by the Windows loader
6441 // PEFileKinds.Dll == 1
6442 // PEFileKinds.ConsoleApplication == 2
6443 // PEFileKinds.WindowApplication == 3
6446 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6447 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6449 if (assemblyb->pekind == 3)
6454 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6456 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6457 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6458 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6459 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6460 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6461 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6463 /* fill data directory entries */
6465 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6466 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6468 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6469 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6471 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6472 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6473 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6474 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6475 /* patch entrypoint name */
6476 if (assemblyb->pekind == 1)
6477 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6479 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6480 /* patch imported function RVA name */
6481 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6482 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6484 /* the import table */
6485 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6486 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6487 /* patch imported dll RVA name and other entries in the dir */
6488 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6489 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6490 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6491 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6492 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6493 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6495 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6496 value = (assembly->text_rva + assembly->imp_names_offset);
6497 *p++ = (value) & 0xff;
6498 *p++ = (value >> 8) & (0xff);
6499 *p++ = (value >> 16) & (0xff);
6500 *p++ = (value >> 24) & (0xff);
6502 /* the CLI header info */
6503 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6504 cli_header->ch_size = GUINT32_FROM_LE (72);
6505 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6506 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6507 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6508 if (assemblyb->entry_point) {
6509 guint32 table_idx = 0;
6510 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6511 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6512 table_idx = methodb->table_idx;
6514 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6516 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6518 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6520 /* The embedded managed resources */
6521 text_offset = assembly->text_rva + assembly->code.index;
6522 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6523 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6524 text_offset += assembly->resources.index;
6525 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6526 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6527 text_offset += assembly->meta_size;
6528 if (assembly->strong_name_size) {
6529 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6530 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6531 text_offset += assembly->strong_name_size;
6534 /* write the section tables and section content */
6535 section = (MonoSectionTable*)(pefile->data + section_start);
6536 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6537 static const char section_names [][7] = {
6538 ".text", ".rsrc", ".reloc"
6540 if (!assembly->sections [i].size)
6542 strcpy (section->st_name, section_names [i]);
6543 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6544 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6545 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6546 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6547 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6548 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6549 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6553 checked_write_file (file, pefile->data, pefile->index);
6555 mono_dynamic_stream_reset (pefile);
6557 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6558 if (!assembly->sections [i].size)
6561 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6562 g_error ("SetFilePointer returned %d\n", GetLastError ());
6565 case MONO_SECTION_TEXT:
6566 /* patch entry point */
6567 p = (guchar*)(assembly->code.data + 2);
6568 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6569 *p++ = (value) & 0xff;
6570 *p++ = (value >> 8) & 0xff;
6571 *p++ = (value >> 16) & 0xff;
6572 *p++ = (value >> 24) & 0xff;
6574 checked_write_file (file, assembly->code.data, assembly->code.index);
6575 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6576 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6577 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6580 g_free (assembly->image.raw_metadata);
6582 case MONO_SECTION_RELOC: {
6586 guint16 type_and_offset;
6590 g_assert (sizeof (reloc) == 12);
6592 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6593 reloc.block_size = GUINT32_FROM_LE (12);
6596 * the entrypoint is always at the start of the text section
6597 * 3 is IMAGE_REL_BASED_HIGHLOW
6598 * 2 is patch_size_rva - text_rva
6600 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6603 checked_write_file (file, &reloc, sizeof (reloc));
6607 case MONO_SECTION_RSRC:
6608 if (assembly->win32_res) {
6610 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6611 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6612 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6616 g_assert_not_reached ();
6620 /* check that the file is properly padded */
6621 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6622 g_error ("SetFilePointer returned %d\n", GetLastError ());
6623 if (! SetEndOfFile (file))
6624 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6626 mono_dynamic_stream_reset (&assembly->code);
6627 mono_dynamic_stream_reset (&assembly->us);
6628 mono_dynamic_stream_reset (&assembly->blob);
6629 mono_dynamic_stream_reset (&assembly->guid);
6630 mono_dynamic_stream_reset (&assembly->sheap);
6632 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6633 g_hash_table_destroy (assembly->blob_cache);
6634 assembly->blob_cache = NULL;
6639 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6642 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6644 g_assert_not_reached ();
6647 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6649 #ifndef DISABLE_REFLECTION_EMIT
6651 MonoReflectionModule *
6652 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6655 MonoReflectionModule *result = NULL;
6658 MonoImageOpenStatus status;
6659 MonoDynamicAssembly *assembly;
6660 guint32 module_count;
6661 MonoImage **new_modules;
6662 gboolean *new_modules_loaded;
6664 name = mono_string_to_utf8 (fileName);
6666 image = mono_image_open (name, &status);
6669 if (status == MONO_IMAGE_ERROR_ERRNO)
6670 exc = mono_get_exception_file_not_found (fileName);
6672 exc = mono_get_exception_bad_image_format (name);
6674 mono_raise_exception (exc);
6679 assembly = ab->dynamic_assembly;
6680 image->assembly = (MonoAssembly*)assembly;
6682 module_count = image->assembly->image->module_count;
6683 new_modules = g_new0 (MonoImage *, module_count + 1);
6684 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6686 if (image->assembly->image->modules)
6687 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6688 if (image->assembly->image->modules_loaded)
6689 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6690 new_modules [module_count] = image;
6691 new_modules_loaded [module_count] = TRUE;
6692 mono_image_addref (image);
6694 g_free (image->assembly->image->modules);
6695 image->assembly->image->modules = new_modules;
6696 image->assembly->image->modules_loaded = new_modules_loaded;
6697 image->assembly->image->module_count ++;
6699 mono_assembly_load_references (image, &status);
6701 mono_image_close (image);
6702 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6705 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6706 mono_error_raise_exception (&error); /* FIXME don't raise here */
6710 #endif /* DISABLE_REFLECTION_EMIT */
6713 * We need to return always the same object for MethodInfo, FieldInfo etc..
6714 * but we need to consider the reflected type.
6715 * type uses a different hash, since it uses custom hash/equal functions.
6720 MonoClass *refclass;
6724 reflected_equal (gconstpointer a, gconstpointer b) {
6725 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6726 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6728 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6732 reflected_hash (gconstpointer a) {
6733 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6734 return mono_aligned_addr_hash (ea->item);
6737 #define CHECK_OBJECT(t,p,k) \
6743 mono_domain_lock (domain); \
6744 if (!domain->refobject_hash) \
6745 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"); \
6746 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6747 mono_domain_unlock (domain); \
6750 mono_domain_unlock (domain); \
6753 #ifdef HAVE_BOEHM_GC
6754 /* ReflectedEntry doesn't need to be GC tracked */
6755 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6756 #define FREE_REFENTRY(entry) g_free ((entry))
6757 #define REFENTRY_REQUIRES_CLEANUP
6759 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6761 #define FREE_REFENTRY(entry)
6764 #define CACHE_OBJECT(t,p,o,k) \
6767 ReflectedEntry pe; \
6769 pe.refclass = (k); \
6770 mono_domain_lock (domain); \
6771 if (!domain->refobject_hash) \
6772 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"); \
6773 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6775 ReflectedEntry *e = ALLOC_REFENTRY; \
6777 e->refclass = (k); \
6778 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6781 mono_domain_unlock (domain); \
6786 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6788 mono_domain_lock (domain);
6789 if (domain->refobject_hash) {
6791 gpointer orig_pe, orig_value;
6794 pe.refclass = klass;
6795 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6796 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6797 FREE_REFENTRY (orig_pe);
6800 mono_domain_unlock (domain);
6803 #ifdef REFENTRY_REQUIRES_CLEANUP
6805 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6807 FREE_REFENTRY (key);
6812 mono_reflection_cleanup_domain (MonoDomain *domain)
6814 if (domain->refobject_hash) {
6815 /*let's avoid scanning the whole hashtable if not needed*/
6816 #ifdef REFENTRY_REQUIRES_CLEANUP
6817 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6819 mono_g_hash_table_destroy (domain->refobject_hash);
6820 domain->refobject_hash = NULL;
6824 #ifndef DISABLE_REFLECTION_EMIT
6826 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6828 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6832 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6834 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6838 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6840 MonoDynamicImage *image = moduleb->dynamic_image;
6841 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6845 MonoImage **new_modules;
6847 char *name, *fqname;
6849 * FIXME: we already created an image in mono_image_basic_init (), but
6850 * we don't know which module it belongs to, since that is only
6851 * determined at assembly save time.
6853 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6854 name = mono_string_to_utf8 (ab->name);
6855 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6856 if (!mono_error_ok (&error)) {
6858 mono_error_raise_exception (&error);
6860 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6862 moduleb->module.image = &image->image;
6863 moduleb->dynamic_image = image;
6864 register_module (mono_object_domain (moduleb), moduleb, image);
6866 /* register the module with the assembly */
6867 ass = ab->dynamic_assembly->assembly.image;
6868 module_count = ass->module_count;
6869 new_modules = g_new0 (MonoImage *, module_count + 1);
6872 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6873 new_modules [module_count] = &image->image;
6874 mono_image_addref (&image->image);
6876 g_free (ass->modules);
6877 ass->modules = new_modules;
6878 ass->module_count ++;
6883 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6885 MonoDynamicImage *image = moduleb->dynamic_image;
6887 g_assert (type->type);
6888 image->wrappers_type = mono_class_from_mono_type (type->type);
6894 * mono_assembly_get_object:
6895 * @domain: an app domain
6896 * @assembly: an assembly
6898 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6900 MonoReflectionAssembly*
6901 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6904 MonoReflectionAssembly *result;
6905 result = mono_assembly_get_object_checked (domain, assembly, &error);
6906 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6910 * mono_assembly_get_object_checked:
6911 * @domain: an app domain
6912 * @assembly: an assembly
6914 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6916 MonoReflectionAssembly*
6917 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6919 MonoReflectionAssembly *res;
6921 mono_error_init (error);
6923 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6924 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6927 res->assembly = assembly;
6929 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6934 MonoReflectionModule*
6935 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6938 MonoReflectionModule *result;
6939 result = mono_module_get_object_checked (domain, image, &error);
6940 mono_error_raise_exception (&error);
6944 MonoReflectionModule*
6945 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6947 MonoReflectionModule *res;
6950 mono_error_init (error);
6951 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6952 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6957 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6960 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6962 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6963 basename = g_path_get_basename (image->name);
6964 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6965 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6969 if (image->assembly->image == image) {
6970 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6974 if (image->assembly->image->modules) {
6975 for (i = 0; i < image->assembly->image->module_count; i++) {
6976 if (image->assembly->image->modules [i] == image)
6977 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6979 g_assert (res->token);
6983 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6986 MonoReflectionModule*
6987 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6990 MonoReflectionModule *result;
6991 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6992 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6996 MonoReflectionModule*
6997 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6999 MonoReflectionModule *res;
7000 MonoTableInfo *table;
7001 guint32 cols [MONO_FILE_SIZE];
7003 guint32 i, name_idx;
7006 mono_error_init (error);
7008 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7012 table = &image->tables [MONO_TABLE_FILE];
7013 g_assert (table_index < table->rows);
7014 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7017 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7020 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7021 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7023 /* Check whenever the row has a corresponding row in the moduleref table */
7024 table = &image->tables [MONO_TABLE_MODULEREF];
7025 for (i = 0; i < table->rows; ++i) {
7026 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7027 val = mono_metadata_string_heap (image, name_idx);
7028 if (strcmp (val, name) == 0)
7029 res->image = image->modules [i];
7032 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7033 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7034 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7035 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7036 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7042 verify_safe_for_managed_space (MonoType *type)
7044 switch (type->type) {
7046 case MONO_TYPE_ARRAY:
7047 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7049 return verify_safe_for_managed_space (type->data.type);
7050 case MONO_TYPE_SZARRAY:
7051 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7052 case MONO_TYPE_GENERICINST: {
7053 MonoGenericInst *inst = type->data.generic_class->inst;
7057 for (i = 0; i < inst->type_argc; ++i)
7058 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7064 case MONO_TYPE_MVAR:
7072 mono_type_normalize (MonoType *type)
7075 MonoGenericClass *gclass;
7076 MonoGenericInst *ginst;
7078 MonoGenericContainer *gcontainer;
7079 MonoType **argv = NULL;
7080 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7082 if (type->type != MONO_TYPE_GENERICINST)
7085 gclass = type->data.generic_class;
7086 ginst = gclass->context.class_inst;
7087 if (!ginst->is_open)
7090 gtd = gclass->container_class;
7091 gcontainer = gtd->generic_container;
7092 argv = g_newa (MonoType*, ginst->type_argc);
7094 for (i = 0; i < ginst->type_argc; ++i) {
7095 MonoType *t = ginst->type_argv [i], *norm;
7096 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7097 is_denorm_gtd = FALSE;
7098 norm = mono_type_normalize (t);
7101 requires_rebind = TRUE;
7105 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7107 if (requires_rebind) {
7108 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7109 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7115 * mono_type_get_object:
7116 * @domain: an app domain
7119 * Return an System.MonoType object representing the type @type.
7122 mono_type_get_object (MonoDomain *domain, MonoType *type)
7125 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7126 mono_error_raise_exception (&error);
7132 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7134 MonoType *norm_type;
7135 MonoReflectionType *res;
7138 mono_error_init (error);
7140 klass = mono_class_from_mono_type (type);
7142 /*we must avoid using @type as it might have come
7143 * from a mono_metadata_type_dup and the caller
7144 * expects that is can be freed.
7145 * Using the right type from
7147 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7149 /* void is very common */
7150 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7151 return (MonoReflectionType*)domain->typeof_void;
7154 * If the vtable of the given class was already created, we can use
7155 * the MonoType from there and avoid all locking and hash table lookups.
7157 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7158 * that the resulting object is different.
7160 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7161 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7162 if (vtable && vtable->type)
7163 return (MonoReflectionType *)vtable->type;
7166 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7167 mono_domain_lock (domain);
7168 if (!domain->type_hash)
7169 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7170 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7171 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7172 mono_domain_unlock (domain);
7173 mono_loader_unlock ();
7177 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7178 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7179 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7180 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7181 * artifact of how generics are encoded and should be transparent to managed code so we
7182 * need to weed out this diference when retrieving managed System.Type objects.
7184 norm_type = mono_type_normalize (type);
7185 if (norm_type != type) {
7186 res = mono_type_get_object_checked (domain, norm_type, error);
7187 if (!mono_error_ok (error))
7189 mono_g_hash_table_insert (domain->type_hash, type, res);
7190 mono_domain_unlock (domain);
7191 mono_loader_unlock ();
7195 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7196 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7199 if (!verify_safe_for_managed_space (type)) {
7200 mono_domain_unlock (domain);
7201 mono_loader_unlock ();
7202 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7206 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7207 gboolean is_type_done = TRUE;
7208 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7209 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7210 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7212 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7213 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7215 if (gparam->owner && gparam->owner->is_method) {
7216 MonoMethod *method = gparam->owner->owner.method;
7217 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7218 is_type_done = FALSE;
7219 } else if (gparam->owner && !gparam->owner->is_method) {
7220 MonoClass *klass = gparam->owner->owner.klass;
7221 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7222 is_type_done = FALSE;
7226 /* g_assert_not_reached (); */
7227 /* should this be considered an error condition? */
7228 if (is_type_done && !type->byref) {
7229 mono_domain_unlock (domain);
7230 mono_loader_unlock ();
7231 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7234 /* This is stored in vtables/JITted code so it has to be pinned */
7235 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7236 if (!mono_error_ok (error))
7240 mono_g_hash_table_insert (domain->type_hash, type, res);
7242 if (type->type == MONO_TYPE_VOID)
7243 domain->typeof_void = (MonoObject*)res;
7245 mono_domain_unlock (domain);
7246 mono_loader_unlock ();
7251 * mono_method_get_object:
7252 * @domain: an app domain
7254 * @refclass: the reflected type (can be NULL)
7256 * Return an System.Reflection.MonoMethod object representing the method @method.
7258 MonoReflectionMethod*
7259 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7262 MonoReflectionMethod *ret = NULL;
7263 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7264 mono_error_raise_exception (&error);
7269 * mono_method_get_object_checked:
7270 * @domain: an app domain
7272 * @refclass: the reflected type (can be NULL)
7273 * @error: set on error.
7275 * Return an System.Reflection.MonoMethod object representing the method @method.
7276 * Returns NULL and sets @error on error.
7278 MonoReflectionMethod*
7279 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7282 * We use the same C representation for methods and constructors, but the type
7283 * name in C# is different.
7285 MonoReflectionType *rt;
7287 MonoReflectionMethod *ret;
7289 mono_error_init (error);
7291 if (method->is_inflated) {
7292 MonoReflectionGenericMethod *gret;
7295 refclass = method->klass;
7296 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7297 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7298 klass = mono_class_get_mono_generic_cmethod_class ();
7300 klass = mono_class_get_mono_generic_method_class ();
7302 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7303 if (!mono_error_ok (error))
7305 gret->method.method = method;
7307 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7309 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7310 if (!mono_error_ok (error))
7313 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7315 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7319 refclass = method->klass;
7321 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7322 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7323 klass = mono_class_get_mono_cmethod_class ();
7326 klass = mono_class_get_mono_method_class ();
7328 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7329 if (!mono_error_ok (error))
7331 ret->method = method;
7333 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7334 if (!mono_error_ok (error))
7337 MONO_OBJECT_SETREF (ret, reftype, rt);
7339 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7342 g_assert (!mono_error_ok (error));
7347 * mono_method_clear_object:
7349 * Clear the cached reflection objects for the dynamic method METHOD.
7352 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7355 g_assert (method_is_dynamic (method));
7357 klass = method->klass;
7359 clear_cached_object (domain, method, klass);
7360 klass = klass->parent;
7362 /* Added by mono_param_get_objects () */
7363 clear_cached_object (domain, &(method->signature), NULL);
7364 klass = method->klass;
7366 clear_cached_object (domain, &(method->signature), klass);
7367 klass = klass->parent;
7372 * mono_field_get_object:
7373 * @domain: an app domain
7377 * Return an System.Reflection.MonoField object representing the field @field
7380 MonoReflectionField*
7381 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7384 MonoReflectionField *result;
7385 result = mono_field_get_object_checked (domain, klass, field, &error);
7386 mono_error_raise_exception (&error);
7391 * mono_field_get_object_checked:
7392 * @domain: an app domain
7395 * @error: set on error
7397 * Return an System.Reflection.MonoField object representing the field @field
7398 * in class @klass. On error, returns NULL and sets @error.
7400 MonoReflectionField*
7401 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7403 MonoReflectionType *rt;
7404 MonoReflectionField *res;
7406 mono_error_init (error);
7408 CHECK_OBJECT (MonoReflectionField *, field, klass);
7409 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7414 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7416 if (is_field_on_inst (field)) {
7417 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7419 rt = mono_type_get_object_checked (domain, field->type, error);
7420 if (!mono_error_ok (error))
7423 MONO_OBJECT_SETREF (res, type, rt);
7426 rt = mono_type_get_object_checked (domain, field->type, error);
7427 if (!mono_error_ok (error))
7430 MONO_OBJECT_SETREF (res, type, rt);
7432 res->attrs = mono_field_get_flags (field);
7434 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7438 * mono_property_get_object:
7439 * @domain: an app domain
7441 * @property: a property
7443 * Return an System.Reflection.MonoProperty object representing the property @property
7446 MonoReflectionProperty*
7447 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7450 MonoReflectionProperty *result;
7451 result = mono_property_get_object_checked (domain, klass, property, &error);
7452 mono_error_raise_exception (&error);
7457 * mono_property_get_object:
7458 * @domain: an app domain
7460 * @property: a property
7461 * @error: set on error
7463 * Return an System.Reflection.MonoProperty object representing the property @property
7464 * in class @klass. On error returns NULL and sets @error.
7466 MonoReflectionProperty*
7467 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7469 MonoReflectionProperty *res;
7471 mono_error_init (error);
7473 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7474 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7478 res->property = property;
7479 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7483 * mono_event_get_object:
7484 * @domain: an app domain
7488 * Return an System.Reflection.MonoEvent object representing the event @event
7491 MonoReflectionEvent*
7492 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7495 MonoReflectionEvent *result;
7496 result = mono_event_get_object_checked (domain, klass, event, &error);
7497 mono_error_raise_exception (&error);
7502 * mono_event_get_object_checked:
7503 * @domain: an app domain
7506 * @error: set on error
7508 * Return an System.Reflection.MonoEvent object representing the event @event
7509 * in class @klass. On failure sets @error and returns NULL
7511 MonoReflectionEvent*
7512 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7514 MonoReflectionEvent *res;
7515 MonoReflectionMonoEvent *mono_event;
7517 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7518 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7521 mono_event->klass = klass;
7522 mono_event->event = event;
7523 res = (MonoReflectionEvent*)mono_event;
7524 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7528 * mono_get_reflection_missing_object:
7529 * @domain: Domain where the object lives
7531 * Returns the System.Reflection.Missing.Value singleton object
7532 * (of type System.Reflection.Missing).
7534 * Used as the value for ParameterInfo.DefaultValue when Optional
7538 mono_get_reflection_missing_object (MonoDomain *domain)
7541 static MonoClassField *missing_value_field = NULL;
7543 if (!missing_value_field) {
7544 MonoClass *missing_klass;
7545 missing_klass = mono_class_get_missing_class ();
7546 mono_class_init (missing_klass);
7547 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7548 g_assert (missing_value_field);
7550 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7556 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7559 *dbnull = mono_get_dbnull_object (domain);
7564 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7566 if (!*reflection_missing)
7567 *reflection_missing = mono_get_reflection_missing_object (domain);
7568 return *reflection_missing;
7572 * mono_param_get_objects:
7573 * @domain: an app domain
7576 * Return an System.Reflection.ParameterInfo array object representing the parameters
7577 * in the method @method.
7580 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7582 static MonoClass *System_Reflection_ParameterInfo;
7583 static MonoClass *System_Reflection_ParameterInfo_array;
7585 MonoArray *res = NULL;
7586 MonoReflectionMethod *member = NULL;
7587 MonoReflectionParameter *param = NULL;
7588 char **names = NULL, **blobs = NULL;
7589 guint32 *types = NULL;
7590 MonoType *type = NULL;
7591 MonoObject *dbnull = NULL;
7592 MonoObject *missing = NULL;
7593 MonoMarshalSpec **mspecs = NULL;
7594 MonoMethodSignature *sig = NULL;
7595 MonoVTable *pinfo_vtable;
7596 MonoReflectionType *rt;
7599 mono_error_init (&error);
7601 if (!System_Reflection_ParameterInfo_array) {
7604 klass = mono_class_get_mono_parameter_info_class ();
7606 mono_memory_barrier ();
7607 System_Reflection_ParameterInfo = klass;
7610 klass = mono_array_class_get (klass, 1);
7611 mono_memory_barrier ();
7612 System_Reflection_ParameterInfo_array = klass;
7615 sig = mono_method_signature_checked (method, &error);
7616 if (!mono_error_ok (&error))
7619 if (!sig->param_count) {
7620 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7627 /* Note: the cache is based on the address of the signature into the method
7628 * since we already cache MethodInfos with the method as keys.
7630 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7632 member = mono_method_get_object_checked (domain, method, refclass, &error);
7635 names = g_new (char *, sig->param_count);
7636 mono_method_get_param_names (method, (const char **) names);
7638 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7639 mono_method_get_marshal_info (method, mspecs);
7641 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7645 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7646 for (i = 0; i < sig->param_count; ++i) {
7647 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7651 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7655 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7657 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7659 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7661 param->PositionImpl = i;
7662 param->AttrsImpl = sig->params [i]->attrs;
7664 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7665 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7666 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7668 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7672 blobs = g_new0 (char *, sig->param_count);
7673 types = g_new0 (guint32, sig->param_count);
7674 get_default_param_value_blobs (method, blobs, types);
7677 /* Build MonoType for the type from the Constant Table */
7679 type = g_new0 (MonoType, 1);
7680 type->type = (MonoTypeEnum)types [i];
7681 type->data.klass = NULL;
7682 if (types [i] == MONO_TYPE_CLASS)
7683 type->data.klass = mono_defaults.object_class;
7684 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7685 /* For enums, types [i] contains the base type */
7687 type->type = MONO_TYPE_VALUETYPE;
7688 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7690 type->data.klass = mono_class_from_mono_type (type);
7692 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7694 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7695 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7696 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7697 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7699 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7704 if (mspecs [i + 1]) {
7705 MonoReflectionMarshalAsAttribute* mobj;
7706 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7709 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7712 mono_array_setref (res, i, param);
7722 for (i = sig->param_count; i >= 0; i--) {
7724 mono_metadata_free_marshal_spec (mspecs [i]);
7729 mono_error_raise_exception (&error); /* FIXME don't raise here */
7731 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7735 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7737 return mono_param_get_objects_internal (domain, method, NULL);
7741 * mono_method_body_get_object:
7742 * @domain: an app domain
7745 * Return an System.Reflection.MethodBody object representing the method @method.
7747 MonoReflectionMethodBody*
7748 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7751 MonoReflectionMethodBody *ret;
7752 MonoMethodHeader *header;
7754 MonoReflectionType *rt;
7755 guint32 method_rva, local_var_sig_token;
7757 unsigned char format, flags;
7760 /* for compatibility with .net */
7761 if (method_is_dynamic (method))
7762 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7764 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7766 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7767 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7768 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7769 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7770 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7773 image = method->klass->image;
7774 header = mono_method_get_header_checked (method, &error);
7775 mono_error_raise_exception (&error); /* FIXME don't raise here */
7777 if (!image_is_dynamic (image)) {
7778 /* Obtain local vars signature token */
7779 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7780 ptr = mono_image_rva_map (image, method_rva);
7781 flags = *(const unsigned char *) ptr;
7782 format = flags & METHOD_HEADER_FORMAT_MASK;
7784 case METHOD_HEADER_TINY_FORMAT:
7785 local_var_sig_token = 0;
7787 case METHOD_HEADER_FAT_FORMAT:
7791 local_var_sig_token = read32 (ptr);
7794 g_assert_not_reached ();
7797 local_var_sig_token = 0; //FIXME
7799 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7800 mono_error_raise_exception (&error); /* FIXME don't raise here */
7802 ret->init_locals = header->init_locals;
7803 ret->max_stack = header->max_stack;
7804 ret->local_var_sig_token = local_var_sig_token;
7805 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7806 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7809 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7810 for (i = 0; i < header->num_locals; ++i) {
7811 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7812 mono_error_raise_exception (&error); /* FIXME don't raise here */
7814 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7815 mono_error_raise_exception (&error); /* FIXME don't raise here */
7817 MONO_OBJECT_SETREF (info, local_type, rt);
7819 info->is_pinned = header->locals [i]->pinned;
7820 info->local_index = i;
7821 mono_array_setref (ret->locals, i, info);
7825 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7826 for (i = 0; i < header->num_clauses; ++i) {
7827 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7828 mono_error_raise_exception (&error); /* FIXME don't raise here */
7829 MonoExceptionClause *clause = &header->clauses [i];
7831 info->flags = clause->flags;
7832 info->try_offset = clause->try_offset;
7833 info->try_length = clause->try_len;
7834 info->handler_offset = clause->handler_offset;
7835 info->handler_length = clause->handler_len;
7836 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7837 info->filter_offset = clause->data.filter_offset;
7838 else if (clause->data.catch_class) {
7839 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7840 mono_error_raise_exception (&error); /* FIXME don't raise here */
7842 MONO_OBJECT_SETREF (info, catch_type, rt);
7845 mono_array_setref (ret->clauses, i, info);
7848 mono_metadata_free_mh (header);
7849 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7854 * mono_get_dbnull_object:
7855 * @domain: Domain where the object lives
7857 * Returns the System.DBNull.Value singleton object
7859 * Used as the value for ParameterInfo.DefaultValue
7862 mono_get_dbnull_object (MonoDomain *domain)
7865 static MonoClassField *dbnull_value_field = NULL;
7867 if (!dbnull_value_field) {
7868 MonoClass *dbnull_klass;
7869 dbnull_klass = mono_class_get_dbnull_class ();
7870 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7871 g_assert (dbnull_value_field);
7873 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7879 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7881 guint32 param_index, i, lastp, crow = 0;
7882 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7885 MonoClass *klass = method->klass;
7886 MonoImage *image = klass->image;
7887 MonoMethodSignature *methodsig = mono_method_signature (method);
7889 MonoTableInfo *constt;
7890 MonoTableInfo *methodt;
7891 MonoTableInfo *paramt;
7893 if (!methodsig->param_count)
7896 mono_class_init (klass);
7898 if (image_is_dynamic (klass->image)) {
7899 MonoReflectionMethodAux *aux;
7900 if (method->is_inflated)
7901 method = ((MonoMethodInflated*)method)->declaring;
7902 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7903 if (aux && aux->param_defaults) {
7904 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7905 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7910 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7911 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7912 constt = &image->tables [MONO_TABLE_CONSTANT];
7914 idx = mono_method_get_index (method) - 1;
7915 g_assert (idx != -1);
7917 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7918 if (idx + 1 < methodt->rows)
7919 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7921 lastp = paramt->rows + 1;
7923 for (i = param_index; i < lastp; ++i) {
7926 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7927 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7929 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7932 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7937 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7938 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7939 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7946 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7952 MonoType *basetype = type;
7957 klass = mono_class_from_mono_type (type);
7958 if (klass->valuetype) {
7959 object = mono_object_new_checked (domain, klass, &error);
7960 mono_error_raise_exception (&error); /* FIXME don't raise here */
7961 retval = ((gchar *) object + sizeof (MonoObject));
7962 if (klass->enumtype)
7963 basetype = mono_class_enum_basetype (klass);
7968 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7975 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7978 gboolean quoted = FALSE;
7980 memset (assembly, 0, sizeof (MonoAssemblyName));
7981 assembly->culture = "";
7982 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7989 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8000 /* Remove trailing whitespace */
8002 while (*s && g_ascii_isspace (*s))
8005 while (g_ascii_isspace (*p))
8008 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8010 assembly->major = strtoul (p, &s, 10);
8011 if (s == p || *s != '.')
8014 assembly->minor = strtoul (p, &s, 10);
8015 if (s == p || *s != '.')
8018 assembly->build = strtoul (p, &s, 10);
8019 if (s == p || *s != '.')
8022 assembly->revision = strtoul (p, &s, 10);
8026 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8028 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8029 assembly->culture = "";
8032 assembly->culture = p;
8033 while (*p && *p != ',') {
8037 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8039 if (strncmp (p, "null", 4) == 0) {
8044 while (*p && *p != ',') {
8047 len = (p - start + 1);
8048 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8049 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8050 g_strlcpy ((char*)assembly->public_key_token, start, len);
8053 while (*p && *p != ',')
8057 while (g_ascii_isspace (*p) || *p == ',') {
8071 * mono_reflection_parse_type:
8074 * Parse a type name as accepted by the GetType () method and output the info
8075 * extracted in the info structure.
8076 * the name param will be mangled, so, make a copy before passing it to this function.
8077 * The fields in info will be valid until the memory pointed to by name is valid.
8079 * See also mono_type_get_name () below.
8081 * Returns: 0 on parse error.
8084 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8085 MonoTypeNameParse *info)
8087 char *start, *p, *w, *last_point, *startn;
8088 int in_modifiers = 0;
8089 int isbyref = 0, rank = 0, isptr = 0;
8091 start = p = w = name;
8093 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8094 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8095 info->name = info->name_space = NULL;
8096 info->nested = NULL;
8097 info->modifiers = NULL;
8098 info->type_arguments = NULL;
8100 /* last_point separates the namespace from the name */
8103 while (*p == ' ') p++, start++, w++, name++;
8108 *p = 0; /* NULL terminate the name */
8110 info->nested = g_list_append (info->nested, startn);
8111 /* we have parsed the nesting namespace + name */
8115 info->name_space = start;
8117 info->name = last_point + 1;
8119 info->name_space = (char *)"";
8147 info->name_space = start;
8149 info->name = last_point + 1;
8151 info->name_space = (char *)"";
8158 if (isbyref) /* only one level allowed by the spec */
8162 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8166 if (isbyref) /* pointer to ref not okay */
8168 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8173 if (isbyref) /* array of ref and generic ref are not okay */
8175 //Decide if it's an array of a generic argument list
8180 if (*p == ',' || *p == '*' || *p == ']') { //array
8188 else if (*p == '*') /* '*' means unknown lower bound */
8189 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8196 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8198 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8201 info->type_arguments = g_ptr_array_new ();
8203 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8204 gboolean fqname = FALSE;
8206 g_ptr_array_add (info->type_arguments, subinfo);
8208 while (*p == ' ') p++;
8214 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8217 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8218 if (fqname && (*p != ']')) {
8226 while (*p && (*p != ']'))
8234 if (g_ascii_isspace (*aname)) {
8241 !assembly_name_to_aname (&subinfo->assembly, aname))
8243 } else if (fqname && (*p == ']')) {
8265 if (g_ascii_isspace (*p)) {
8272 return 0; /* missing assembly name */
8273 if (!assembly_name_to_aname (&info->assembly, p))
8279 if (info->assembly.name)
8282 // *w = 0; /* terminate class name */
8284 if (!info->name || !*info->name)
8288 /* add other consistency checks */
8294 * mono_identifier_unescape_type_name_chars:
8295 * @identifier: the display name of a mono type
8298 * The name in internal form, that is without escaping backslashes.
8300 * The string is modified in place!
8303 mono_identifier_unescape_type_name_chars(char* identifier)
8308 for (w = r = identifier; *r != 0; r++)
8326 mono_identifier_unescape_info (MonoTypeNameParse* info);
8329 unescape_each_type_argument(void* data, void* user_data)
8331 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8332 mono_identifier_unescape_info (info);
8336 unescape_each_nested_name (void* data, void* user_data)
8338 char* nested_name = (char*) data;
8339 mono_identifier_unescape_type_name_chars(nested_name);
8343 * mono_identifier_unescape_info:
8345 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8349 * Destructively updates the info by unescaping the identifiers that
8350 * comprise the type namespace, name, nested types (if any) and
8351 * generic type arguments (if any).
8353 * The resulting info has the names in internal form.
8357 mono_identifier_unescape_info (MonoTypeNameParse *info)
8361 mono_identifier_unescape_type_name_chars(info->name_space);
8362 mono_identifier_unescape_type_name_chars(info->name);
8363 // but don't escape info->assembly
8364 if (info->type_arguments)
8365 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8367 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8371 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8373 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8375 mono_identifier_unescape_info (info);
8381 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8383 gboolean type_resolve = FALSE;
8385 MonoImage *rootimage = image;
8387 if (info->assembly.name) {
8388 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8389 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8391 * This could happen in the AOT compiler case when the search hook is not
8394 assembly = image->assembly;
8396 /* then we must load the assembly ourselve - see #60439 */
8397 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8401 image = assembly->image;
8402 } else if (!image) {
8403 image = mono_defaults.corlib;
8406 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8407 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8408 image = mono_defaults.corlib;
8409 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8416 * mono_reflection_get_type_internal:
8418 * Returns: may return NULL on success, sets error on failure.
8421 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8426 gboolean bounded = FALSE;
8428 mono_error_init (error);
8430 image = mono_defaults.corlib;
8433 rootimage = mono_defaults.corlib;
8436 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8438 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8443 for (mod = info->nested; mod; mod = mod->next) {
8444 gpointer iter = NULL;
8448 mono_class_init (parent);
8450 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8452 char *nested_name, *nested_nspace;
8453 gboolean match = TRUE;
8455 lastp = strrchr ((const char *)mod->data, '.');
8457 /* Nested classes can have namespaces */
8460 nested_name = g_strdup (lastp + 1);
8461 nspace_len = lastp - (char*)mod->data;
8462 nested_nspace = (char *)g_malloc (nspace_len + 1);
8463 memcpy (nested_nspace, mod->data, nspace_len);
8464 nested_nspace [nspace_len] = '\0';
8467 nested_name = (char *)mod->data;
8468 nested_nspace = NULL;
8471 if (nested_nspace) {
8473 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8476 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8482 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8485 if (strcmp (klass->name, nested_name) != 0)
8490 g_free (nested_name);
8491 g_free (nested_nspace);
8503 if (info->type_arguments) {
8504 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8505 MonoReflectionType *the_type;
8509 for (i = 0; i < info->type_arguments->len; i++) {
8510 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8512 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8513 if (!type_args [i]) {
8519 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8523 instance = mono_reflection_bind_generic_parameters (
8524 the_type, info->type_arguments->len, type_args);
8530 klass = mono_class_from_mono_type (instance);
8533 for (mod = info->modifiers; mod; mod = mod->next) {
8534 modval = GPOINTER_TO_UINT (mod->data);
8535 if (!modval) { /* byref: must be last modifier */
8536 return &klass->this_arg;
8537 } else if (modval == -1) {
8538 klass = mono_ptr_class_get (&klass->byval_arg);
8539 } else if (modval == -2) {
8541 } else { /* array rank */
8542 klass = mono_bounded_array_class_get (klass, modval, bounded);
8546 return &klass->byval_arg;
8550 * mono_reflection_get_type:
8551 * @image: a metadata context
8552 * @info: type description structure
8553 * @ignorecase: flag for case-insensitive string compares
8554 * @type_resolve: whenever type resolve was already tried
8556 * Build a MonoType from the type description in @info.
8561 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8562 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8566 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8568 MonoReflectionAssemblyBuilder *abuilder;
8572 mono_error_init (error);
8573 g_assert (assembly_is_dynamic (assembly));
8574 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8578 /* Enumerate all modules */
8581 if (abuilder->modules) {
8582 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8583 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8584 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8587 if (!mono_error_ok (error))
8592 if (!type && abuilder->loaded_modules) {
8593 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8594 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8595 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8598 if (!mono_error_ok (error))
8607 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8611 MonoReflectionAssembly *assembly;
8615 if (image && image_is_dynamic (image))
8616 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8618 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8620 if (!mono_error_ok (&error))
8621 mono_error_raise_exception (&error); /* FIXME don't raise here */
8625 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8632 *type_resolve = TRUE;
8635 /* Reconstruct the type name */
8636 fullName = g_string_new ("");
8637 if (info->name_space && (info->name_space [0] != '\0'))
8638 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8640 g_string_printf (fullName, "%s", info->name);
8641 for (mod = info->nested; mod; mod = mod->next)
8642 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8644 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8645 mono_error_raise_exception (&error); /* FIXME don't raise here */
8648 if (assembly_is_dynamic (assembly->assembly))
8649 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8650 info, ignorecase, &error);
8652 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8653 info, ignorecase, &error);
8655 g_string_free (fullName, TRUE);
8656 if (!mono_error_ok (&error))
8657 mono_error_raise_exception (&error); /* FIXME don't raise here */
8662 mono_reflection_free_type_info (MonoTypeNameParse *info)
8664 g_list_free (info->modifiers);
8665 g_list_free (info->nested);
8667 if (info->type_arguments) {
8670 for (i = 0; i < info->type_arguments->len; i++) {
8671 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8673 mono_reflection_free_type_info (subinfo);
8674 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8678 g_ptr_array_free (info->type_arguments, TRUE);
8683 * mono_reflection_type_from_name:
8685 * @image: a metadata context (can be NULL).
8687 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8688 * it defaults to get the type from @image or, if @image is NULL or loading
8689 * from it fails, uses corlib.
8693 mono_reflection_type_from_name (char *name, MonoImage *image)
8695 MonoType *type = NULL;
8696 MonoTypeNameParse info;
8699 /* Make a copy since parse_type modifies its argument */
8700 tmp = g_strdup (name);
8702 /*g_print ("requested type %s\n", str);*/
8703 if (mono_reflection_parse_type (tmp, &info)) {
8704 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8708 mono_reflection_free_type_info (&info);
8713 * mono_reflection_get_token:
8715 * Return the metadata token of OBJ which should be an object
8716 * representing a metadata element.
8719 mono_reflection_get_token (MonoObject *obj)
8725 klass = obj->vtable->klass;
8727 if (strcmp (klass->name, "MethodBuilder") == 0) {
8728 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8730 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8731 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8732 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8734 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8735 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8736 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8738 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8739 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8740 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8741 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8742 } else if (strcmp (klass->name, "MonoType") == 0) {
8743 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8744 mono_error_raise_exception (&error); /* FIXME don't raise here */
8745 MonoClass *mc = mono_class_from_mono_type (type);
8746 if (!mono_class_init (mc))
8747 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8749 token = mc->type_token;
8750 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8751 strcmp (klass->name, "MonoMethod") == 0 ||
8752 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8753 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8754 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8755 if (m->method->is_inflated) {
8756 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8757 return inflated->declaring->token;
8759 token = m->method->token;
8761 } else if (strcmp (klass->name, "MonoField") == 0) {
8762 MonoReflectionField *f = (MonoReflectionField*)obj;
8764 if (is_field_on_inst (f->field)) {
8765 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8767 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8768 int field_index = f->field - dgclass->fields;
8771 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8772 obj = dgclass->field_objects [field_index];
8773 return mono_reflection_get_token (obj);
8776 token = mono_class_get_field_token (f->field);
8777 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8778 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8780 token = mono_class_get_property_token (p->property);
8781 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8782 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8784 token = mono_class_get_event_token (p->event);
8785 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8786 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8787 MonoClass *member_class = mono_object_class (p->MemberImpl);
8788 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8790 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8791 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8792 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8795 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8796 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8798 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8799 MonoException *ex = mono_get_exception_not_implemented (msg);
8801 mono_raise_exception (ex);
8808 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8812 int slen = mono_metadata_decode_value (p, &p);
8814 mono_error_init (error);
8816 n = (char *)g_memdup (p, slen + 1);
8818 t = mono_reflection_type_from_name (n, image);
8820 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8821 /* We don't free n, it's consumed by mono_error */
8822 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8828 return mono_class_from_mono_type (t);
8832 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8834 int slen, type = t->type;
8835 MonoClass *tklass = t->data.klass;
8837 mono_error_init (error);
8843 case MONO_TYPE_BOOLEAN: {
8844 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8849 case MONO_TYPE_CHAR:
8851 case MONO_TYPE_I2: {
8852 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8857 #if SIZEOF_VOID_P == 4
8863 case MONO_TYPE_I4: {
8864 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8869 #if SIZEOF_VOID_P == 8
8870 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8874 case MONO_TYPE_I8: {
8875 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8880 case MONO_TYPE_R8: {
8881 double *val = (double *)g_malloc (sizeof (double));
8886 case MONO_TYPE_VALUETYPE:
8887 if (t->data.klass->enumtype) {
8888 type = mono_class_enum_basetype (t->data.klass)->type;
8891 MonoClass *k = t->data.klass;
8893 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8894 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8900 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8903 case MONO_TYPE_STRING:
8904 if (*p == (char)0xFF) {
8908 slen = mono_metadata_decode_value (p, &p);
8910 return mono_string_new_len (mono_domain_get (), p, slen);
8911 case MONO_TYPE_CLASS: {
8912 MonoReflectionType *rt;
8915 if (*p == (char)0xFF) {
8920 slen = mono_metadata_decode_value (p, &p);
8921 n = (char *)g_memdup (p, slen + 1);
8923 t = mono_reflection_type_from_name (n, image);
8925 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8926 /* We don't free n, it's consumed by mono_error */
8927 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8933 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8934 if (!mono_error_ok (error))
8939 case MONO_TYPE_OBJECT: {
8942 MonoClass *subc = NULL;
8947 } else if (subt == 0x0E) {
8948 type = MONO_TYPE_STRING;
8950 } else if (subt == 0x1D) {
8951 MonoType simple_type = {{0}};
8955 type = MONO_TYPE_SZARRAY;
8956 if (etype == 0x50) {
8957 tklass = mono_defaults.systemtype_class;
8958 } else if (etype == 0x55) {
8959 tklass = load_cattr_enum_type (image, p, &p, error);
8960 if (!mono_error_ok (error))
8964 /* See Partition II, Appendix B3 */
8965 etype = MONO_TYPE_OBJECT;
8966 simple_type.type = (MonoTypeEnum)etype;
8967 tklass = mono_class_from_mono_type (&simple_type);
8970 } else if (subt == 0x55) {
8973 slen = mono_metadata_decode_value (p, &p);
8974 n = (char *)g_memdup (p, slen + 1);
8976 t = mono_reflection_type_from_name (n, image);
8978 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8979 /* We don't free n, it's consumed by mono_error */
8980 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8985 subc = mono_class_from_mono_type (t);
8986 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8987 MonoType simple_type = {{0}};
8988 simple_type.type = (MonoTypeEnum)subt;
8989 subc = mono_class_from_mono_type (&simple_type);
8991 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8993 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8995 if (mono_error_ok (error)) {
8996 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8997 g_assert (!subc->has_references);
8998 if (mono_error_ok (error))
8999 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9005 case MONO_TYPE_SZARRAY: {
9007 guint32 i, alen, basetype;
9010 if (alen == 0xffffffff) {
9014 arr = mono_array_new (mono_domain_get(), tklass, alen);
9015 basetype = tklass->byval_arg.type;
9016 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9017 basetype = mono_class_enum_basetype (tklass)->type;
9022 case MONO_TYPE_BOOLEAN:
9023 for (i = 0; i < alen; i++) {
9024 MonoBoolean val = *p++;
9025 mono_array_set (arr, MonoBoolean, i, val);
9028 case MONO_TYPE_CHAR:
9031 for (i = 0; i < alen; i++) {
9032 guint16 val = read16 (p);
9033 mono_array_set (arr, guint16, i, val);
9040 for (i = 0; i < alen; i++) {
9041 guint32 val = read32 (p);
9042 mono_array_set (arr, guint32, i, val);
9047 for (i = 0; i < alen; i++) {
9050 mono_array_set (arr, double, i, val);
9056 for (i = 0; i < alen; i++) {
9057 guint64 val = read64 (p);
9058 mono_array_set (arr, guint64, i, val);
9062 case MONO_TYPE_CLASS:
9063 case MONO_TYPE_OBJECT:
9064 case MONO_TYPE_STRING:
9065 case MONO_TYPE_SZARRAY:
9066 for (i = 0; i < alen; i++) {
9067 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9068 if (!mono_error_ok (error))
9070 mono_array_setref (arr, i, item);
9074 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9080 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9086 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9088 static MonoMethod *ctor;
9090 void *params [2], *unboxed;
9092 mono_error_init (error);
9095 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9097 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9098 return_val_if_nok (error, NULL);
9101 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9102 return_val_if_nok (error, NULL);
9103 unboxed = mono_object_unbox (retval);
9105 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9106 return_val_if_nok (error, NULL);
9112 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9114 static MonoMethod *ctor;
9116 void *unboxed, *params [2];
9118 mono_error_init (error);
9121 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9124 params [1] = typedarg;
9125 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9126 return_val_if_nok (error, NULL);
9128 unboxed = mono_object_unbox (retval);
9130 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9131 return_val_if_nok (error, NULL);
9137 type_is_reference (MonoType *type)
9139 switch (type->type) {
9140 case MONO_TYPE_BOOLEAN:
9141 case MONO_TYPE_CHAR:
9154 case MONO_TYPE_VALUETYPE:
9162 free_param_data (MonoMethodSignature *sig, void **params) {
9164 for (i = 0; i < sig->param_count; ++i) {
9165 if (!type_is_reference (sig->params [i]))
9166 g_free (params [i]);
9171 * Find the field index in the metadata FieldDef table.
9174 find_field_index (MonoClass *klass, MonoClassField *field) {
9177 for (i = 0; i < klass->field.count; ++i) {
9178 if (field == &klass->fields [i])
9179 return klass->field.first + 1 + i;
9185 * Find the property index in the metadata Property table.
9188 find_property_index (MonoClass *klass, MonoProperty *property) {
9191 for (i = 0; i < klass->ext->property.count; ++i) {
9192 if (property == &klass->ext->properties [i])
9193 return klass->ext->property.first + 1 + i;
9199 * Find the event index in the metadata Event table.
9202 find_event_index (MonoClass *klass, MonoEvent *event) {
9205 for (i = 0; i < klass->ext->event.count; ++i) {
9206 if (event == &klass->ext->events [i])
9207 return klass->ext->event.first + 1 + i;
9213 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9215 const char *p = (const char*)data;
9217 guint32 i, j, num_named;
9219 void *params_buf [32];
9220 void **params = NULL;
9221 MonoMethodSignature *sig;
9222 MonoObject *exc = NULL;
9224 mono_error_init (error);
9226 mono_class_init (method->klass);
9228 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9229 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9234 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9235 if (!mono_error_ok (error)) return NULL;
9237 mono_runtime_invoke_checked (method, attr, NULL, error);
9238 if (!mono_error_ok (error))
9244 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9247 /*g_print ("got attr %s\n", method->klass->name);*/
9249 sig = mono_method_signature (method);
9250 if (sig->param_count < 32) {
9251 params = params_buf;
9252 memset (params, 0, sizeof (void*) * sig->param_count);
9254 /* Allocate using GC so it gets GC tracking */
9255 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9260 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9261 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9262 if (!mono_error_ok (error))
9267 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9268 if (!mono_error_ok (error)) goto fail;
9270 mono_runtime_try_invoke (method, attr, params, &exc, error);
9271 if (!mono_error_ok (error))
9276 num_named = read16 (named);
9278 for (j = 0; j < num_named; j++) {
9280 char *name, named_type, data_type;
9281 named_type = *named++;
9282 data_type = *named++; /* type of data */
9283 if (data_type == MONO_TYPE_SZARRAY)
9284 data_type = *named++;
9285 if (data_type == MONO_TYPE_ENUM) {
9288 type_len = mono_metadata_decode_blob_size (named, &named);
9289 type_name = (char *)g_malloc (type_len + 1);
9290 memcpy (type_name, named, type_len);
9291 type_name [type_len] = 0;
9293 /* FIXME: lookup the type and check type consistency */
9296 name_len = mono_metadata_decode_blob_size (named, &named);
9297 name = (char *)g_malloc (name_len + 1);
9298 memcpy (name, named, name_len);
9299 name [name_len] = 0;
9301 if (named_type == 0x53) {
9302 MonoClassField *field;
9305 /* how this fail is a blackbox */
9306 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9308 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9313 val = load_cattr_value (image, field->type, named, &named, error);
9314 if (!mono_error_ok (error)) {
9316 if (!type_is_reference (field->type))
9321 mono_field_set_value (attr, field, val);
9322 if (!type_is_reference (field->type))
9324 } else if (named_type == 0x54) {
9327 MonoType *prop_type;
9329 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9332 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9338 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9343 /* can we have more that 1 arg in a custom attr named property? */
9344 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9345 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9347 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9348 if (!mono_error_ok (error)) {
9350 if (!type_is_reference (prop_type))
9351 g_free (pparams [0]);
9356 mono_property_set_value (prop, attr, pparams, NULL);
9357 if (!type_is_reference (prop_type))
9358 g_free (pparams [0]);
9363 free_param_data (method->signature, params);
9364 if (params != params_buf)
9365 mono_gc_free_fixed (params);
9370 free_param_data (method->signature, params);
9371 if (params != params_buf)
9372 mono_gc_free_fixed (params);
9374 mono_raise_exception ((MonoException*)exc);
9379 * mono_reflection_create_custom_attr_data_args:
9381 * Create an array of typed and named arguments from the cattr blob given by DATA.
9382 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9383 * NAMED_ARG_INFO will contain information about the named arguments.
9386 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)
9388 MonoArray *typedargs, *namedargs;
9389 MonoClass *attrklass;
9391 const char *p = (const char*)data;
9393 guint32 i, j, num_named;
9394 CattrNamedArg *arginfo = NULL;
9398 *named_arg_info = NULL;
9400 mono_error_init (error);
9402 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9403 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9407 mono_class_init (method->klass);
9409 domain = mono_domain_get ();
9411 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9414 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9418 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9422 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9423 if (!mono_error_ok (error)) {
9424 if (!type_is_reference (mono_method_signature (method)->params [i]))
9429 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9430 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9431 mono_array_setref (typedargs, i, obj);
9433 if (!type_is_reference (mono_method_signature (method)->params [i]))
9438 num_named = read16 (named);
9439 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9441 attrklass = method->klass;
9443 arginfo = g_new0 (CattrNamedArg, num_named);
9444 *named_arg_info = arginfo;
9446 for (j = 0; j < num_named; j++) {
9448 char *name, named_type, data_type;
9449 named_type = *named++;
9450 data_type = *named++; /* type of data */
9451 if (data_type == MONO_TYPE_SZARRAY)
9452 data_type = *named++;
9453 if (data_type == MONO_TYPE_ENUM) {
9456 type_len = mono_metadata_decode_blob_size (named, &named);
9457 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9460 type_name = (char *)g_malloc (type_len + 1);
9461 memcpy (type_name, named, type_len);
9462 type_name [type_len] = 0;
9464 /* FIXME: lookup the type and check type consistency */
9467 name_len = mono_metadata_decode_blob_size (named, &named);
9468 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9470 name = (char *)g_malloc (name_len + 1);
9471 memcpy (name, named, name_len);
9472 name [name_len] = 0;
9474 if (named_type == 0x53) {
9476 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9484 arginfo [j].type = field->type;
9485 arginfo [j].field = field;
9487 val = load_cattr_value (image, field->type, named, &named, error);
9488 if (!mono_error_ok (error)) {
9489 if (!type_is_reference (field->type))
9495 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9496 mono_array_setref (namedargs, j, obj);
9497 if (!type_is_reference (field->type))
9499 } else if (named_type == 0x54) {
9501 MonoType *prop_type;
9502 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9505 if (!prop || !prop->set) {
9510 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9511 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9513 arginfo [j].type = prop_type;
9514 arginfo [j].prop = prop;
9516 val = load_cattr_value (image, prop_type, named, &named, error);
9517 if (!mono_error_ok (error)) {
9518 if (!type_is_reference (prop_type))
9524 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9525 mono_array_setref (namedargs, j, obj);
9526 if (!type_is_reference (prop_type))
9532 *typed_args = typedargs;
9533 *named_args = namedargs;
9536 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9538 *named_arg_info = NULL;
9542 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9545 MonoArray *typedargs, *namedargs;
9548 CattrNamedArg *arginfo = NULL;
9552 mono_error_init (&error);
9560 image = assembly->assembly->image;
9561 method = ref_method->method;
9562 domain = mono_object_domain (ref_method);
9564 if (!mono_class_init (method->klass))
9565 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9567 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9568 if (!mono_error_ok (&error))
9571 if (mono_loader_get_last_error ()) {
9572 mono_error_set_from_loader_error (&error);
9576 if (!typedargs || !namedargs)
9579 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9580 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9581 MonoObject *typedarg;
9583 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9584 if (!is_ok (&error))
9586 mono_array_setref (typedargs, i, typedarg);
9589 for (i = 0; i < mono_array_length (namedargs); ++i) {
9590 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9591 MonoObject *typedarg, *namedarg, *minfo;
9593 if (arginfo [i].prop) {
9594 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9598 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9599 if (!mono_error_ok (&error))
9603 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9604 if (!is_ok (&error))
9606 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9607 if (!is_ok (&error))
9610 mono_array_setref (namedargs, i, namedarg);
9613 *ctor_args = typedargs;
9614 *named_args = namedargs;
9617 mono_error_raise_exception (&error);
9622 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9624 static MonoMethod *ctor;
9630 mono_error_init (error);
9632 g_assert (image->assembly);
9635 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9637 domain = mono_domain_get ();
9638 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9639 return_val_if_nok (error, NULL);
9640 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9641 return_val_if_nok (error, NULL);
9642 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9643 return_val_if_nok (error, NULL);
9644 params [2] = (gpointer)&cattr->data;
9645 params [3] = &cattr->data_size;
9647 mono_runtime_invoke_checked (ctor, attr, params, error);
9648 return_val_if_nok (error, NULL);
9653 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9659 mono_error_init (error);
9662 for (i = 0; i < cinfo->num_attrs; ++i) {
9663 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9667 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9669 for (i = 0; i < cinfo->num_attrs; ++i) {
9670 if (!cinfo->attrs [i].ctor) {
9671 /* The cattr type is not finished yet */
9672 /* We should include the type name but cinfo doesn't contain it */
9673 mono_error_set_type_load_name (error, NULL, NULL, "");
9676 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9677 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9678 if (!mono_error_ok (error))
9680 mono_array_setref (result, n, attr);
9688 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9691 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9692 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9698 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9704 mono_error_init (error);
9705 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9706 for (i = 0; i < cinfo->num_attrs; ++i) {
9707 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9708 return_val_if_nok (error, NULL);
9709 mono_array_setref (result, i, attr);
9715 * mono_custom_attrs_from_index:
9717 * Returns: NULL if no attributes are found or if a loading error occurs.
9720 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9723 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9724 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9728 * mono_custom_attrs_from_index_checked:
9730 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9733 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9735 guint32 mtoken, i, len;
9736 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9738 MonoCustomAttrInfo *ainfo;
9739 GList *tmp, *list = NULL;
9741 MonoCustomAttrEntry* attr;
9743 mono_error_init (error);
9745 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9747 i = mono_metadata_custom_attrs_from_index (image, idx);
9751 while (i < ca->rows) {
9752 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9754 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9757 len = g_list_length (list);
9760 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9761 ainfo->num_attrs = len;
9762 ainfo->image = image;
9763 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9764 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9765 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9766 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9767 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9768 mtoken |= MONO_TOKEN_METHOD_DEF;
9770 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9771 mtoken |= MONO_TOKEN_MEMBER_REF;
9774 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9777 attr = &ainfo->attrs [i - 1];
9778 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9780 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9786 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9787 /*FIXME raising an exception here doesn't make any sense*/
9788 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9793 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9794 attr->data_size = mono_metadata_decode_value (data, &data);
9795 attr->data = (guchar*)data;
9803 mono_custom_attrs_from_method (MonoMethod *method)
9806 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9807 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9812 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9816 mono_error_init (error);
9819 * An instantiated method has the same cattrs as the generic method definition.
9821 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9822 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9824 if (method->is_inflated)
9825 method = ((MonoMethodInflated *) method)->declaring;
9827 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9828 return lookup_custom_attr (method->klass->image, method);
9831 /* Synthetic methods */
9834 idx = mono_method_get_index (method);
9835 idx <<= MONO_CUSTOM_ATTR_BITS;
9836 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9837 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9841 mono_custom_attrs_from_class (MonoClass *klass)
9844 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9845 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9850 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9854 mono_error_init (error);
9856 if (klass->generic_class)
9857 klass = klass->generic_class->container_class;
9859 if (image_is_dynamic (klass->image))
9860 return lookup_custom_attr (klass->image, klass);
9862 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9863 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9864 idx <<= MONO_CUSTOM_ATTR_BITS;
9865 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9867 idx = mono_metadata_token_index (klass->type_token);
9868 idx <<= MONO_CUSTOM_ATTR_BITS;
9869 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9871 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9875 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9878 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9879 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9884 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9888 mono_error_init (error);
9890 if (image_is_dynamic (assembly->image))
9891 return lookup_custom_attr (assembly->image, assembly);
9892 idx = 1; /* there is only one assembly */
9893 idx <<= MONO_CUSTOM_ATTR_BITS;
9894 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9895 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9898 static MonoCustomAttrInfo*
9899 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9903 if (image_is_dynamic (image))
9904 return lookup_custom_attr (image, image);
9905 idx = 1; /* there is only one module */
9906 idx <<= MONO_CUSTOM_ATTR_BITS;
9907 idx |= MONO_CUSTOM_ATTR_MODULE;
9908 return mono_custom_attrs_from_index_checked (image, idx, error);
9912 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9915 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9916 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9921 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9925 if (image_is_dynamic (klass->image)) {
9926 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9927 return lookup_custom_attr (klass->image, property);
9929 idx = find_property_index (klass, property);
9930 idx <<= MONO_CUSTOM_ATTR_BITS;
9931 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9932 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9936 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9939 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9940 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9945 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9949 if (image_is_dynamic (klass->image)) {
9950 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9951 return lookup_custom_attr (klass->image, event);
9953 idx = find_event_index (klass, event);
9954 idx <<= MONO_CUSTOM_ATTR_BITS;
9955 idx |= MONO_CUSTOM_ATTR_EVENT;
9956 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9960 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9963 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9964 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9969 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9972 mono_error_init (error);
9974 if (image_is_dynamic (klass->image)) {
9975 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9976 return lookup_custom_attr (klass->image, field);
9978 idx = find_field_index (klass, field);
9979 idx <<= MONO_CUSTOM_ATTR_BITS;
9980 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9981 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9985 * mono_custom_attrs_from_param:
9986 * @method: handle to the method that we want to retrieve custom parameter information from
9987 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9989 * The result must be released with mono_custom_attrs_free().
9991 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9994 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9997 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9998 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10003 * mono_custom_attrs_from_param_checked:
10004 * @method: handle to the method that we want to retrieve custom parameter information from
10005 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10006 * @error: set on error
10008 * The result must be released with mono_custom_attrs_free().
10010 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10012 MonoCustomAttrInfo*
10013 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10016 guint32 i, idx, method_index;
10017 guint32 param_list, param_last, param_pos, found;
10019 MonoReflectionMethodAux *aux;
10021 mono_error_init (error);
10024 * An instantiated method has the same cattrs as the generic method definition.
10026 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10027 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10029 if (method->is_inflated)
10030 method = ((MonoMethodInflated *) method)->declaring;
10032 if (image_is_dynamic (method->klass->image)) {
10033 MonoCustomAttrInfo *res, *ainfo;
10036 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10037 if (!aux || !aux->param_cattr)
10040 /* Need to copy since it will be freed later */
10041 ainfo = aux->param_cattr [param];
10044 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10045 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10046 memcpy (res, ainfo, size);
10050 image = method->klass->image;
10051 method_index = mono_method_get_index (method);
10054 ca = &image->tables [MONO_TABLE_METHOD];
10056 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10057 if (method_index == ca->rows) {
10058 ca = &image->tables [MONO_TABLE_PARAM];
10059 param_last = ca->rows + 1;
10061 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10062 ca = &image->tables [MONO_TABLE_PARAM];
10065 for (i = param_list; i < param_last; ++i) {
10066 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10067 if (param_pos == param) {
10075 idx <<= MONO_CUSTOM_ATTR_BITS;
10076 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10077 return mono_custom_attrs_from_index_checked (image, idx, error);
10081 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10085 for (i = 0; i < ainfo->num_attrs; ++i) {
10086 klass = ainfo->attrs [i].ctor->klass;
10087 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10094 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10097 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10098 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10103 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10109 mono_error_init (error);
10112 for (i = 0; i < ainfo->num_attrs; ++i) {
10113 klass = ainfo->attrs [i].ctor->klass;
10114 if (mono_class_has_parent (klass, attr_klass)) {
10119 if (attr_index == -1)
10122 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10123 if (!mono_error_ok (error))
10125 return mono_array_get (attrs, MonoObject*, attr_index);
10129 * mono_reflection_get_custom_attrs_info:
10130 * @obj: a reflection object handle
10132 * Return the custom attribute info for attributes defined for the
10133 * reflection handle @obj. The objects.
10135 * FIXME this function leaks like a sieve for SRE objects.
10137 MonoCustomAttrInfo*
10138 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10141 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10142 mono_error_assert_ok (&error);
10147 * mono_reflection_get_custom_attrs_info_checked:
10148 * @obj: a reflection object handle
10149 * @error: set on error
10151 * Return the custom attribute info for attributes defined for the
10152 * reflection handle @obj. The objects.
10154 * On failure returns NULL and sets @error.
10156 * FIXME this function leaks like a sieve for SRE objects.
10158 MonoCustomAttrInfo*
10159 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10162 MonoCustomAttrInfo *cinfo = NULL;
10164 mono_error_init (error);
10166 klass = obj->vtable->klass;
10167 if (klass == mono_defaults.monotype_class) {
10168 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10169 return_val_if_nok (error, NULL);
10170 klass = mono_class_from_mono_type (type);
10171 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10172 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10173 return_val_if_nok (error, NULL);
10174 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10175 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10176 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10177 return_val_if_nok (error, NULL);
10178 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10179 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10180 cinfo = mono_custom_attrs_from_module (module->image, error);
10181 return_val_if_nok (error, NULL);
10182 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10183 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10184 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10185 return_val_if_nok (error, NULL);
10186 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10187 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10188 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10189 return_val_if_nok (error, NULL);
10190 } else if (strcmp ("MonoField", klass->name) == 0) {
10191 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10192 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10193 return_val_if_nok (error, NULL);
10194 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10195 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10196 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10197 return_val_if_nok (error, NULL);
10198 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10199 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10200 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10201 return_val_if_nok (error, NULL);
10202 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10203 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10204 MonoClass *member_class = mono_object_class (param->MemberImpl);
10205 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10206 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10207 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10208 return_val_if_nok (error, NULL);
10209 } else if (is_sr_mono_property (member_class)) {
10210 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10211 MonoMethod *method;
10212 if (!(method = prop->property->get))
10213 method = prop->property->set;
10216 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10217 return_val_if_nok (error, NULL);
10219 #ifndef DISABLE_REFLECTION_EMIT
10220 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10221 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10222 return_val_if_nok (error, NULL);
10223 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10224 return_val_if_nok (error, NULL);
10225 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10226 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10227 MonoMethod *method = NULL;
10228 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10229 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10230 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10231 method = ((MonoReflectionMethod *)c->cb)->method;
10233 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));
10235 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10236 return_val_if_nok (error, NULL);
10240 char *type_name = mono_type_get_full_name (member_class);
10241 mono_error_set_generic_error (error, "System", "NotSupportedException",
10242 "Custom attributes on a ParamInfo with member %s are not supported",
10244 g_free (type_name);
10247 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10248 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10249 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10250 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10251 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10252 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10253 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10254 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10255 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10256 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10257 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10258 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10259 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10260 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10261 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10262 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10263 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10264 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10265 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10266 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10267 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10268 return_val_if_nok (error, NULL);
10269 } else { /* handle other types here... */
10270 g_error ("get custom attrs not yet supported for %s", klass->name);
10277 * mono_reflection_get_custom_attrs_by_type:
10278 * @obj: a reflection object handle
10280 * Return an array with all the custom attributes defined of the
10281 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10282 * of that type are returned. The objects are fully build. Return NULL if a loading error
10286 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10289 MonoCustomAttrInfo *cinfo;
10291 mono_error_init (error);
10293 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10294 return_val_if_nok (error, NULL);
10296 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10299 if (!cinfo->cached)
10300 mono_custom_attrs_free (cinfo);
10302 mono_loader_assert_no_error ();
10303 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10310 * mono_reflection_get_custom_attrs:
10311 * @obj: a reflection object handle
10313 * Return an array with all the custom attributes defined of the
10314 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10318 mono_reflection_get_custom_attrs (MonoObject *obj)
10322 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10326 * mono_reflection_get_custom_attrs_data:
10327 * @obj: a reflection obj handle
10329 * Returns an array of System.Reflection.CustomAttributeData,
10330 * which include information about attributes reflected on
10331 * types loaded using the Reflection Only methods
10334 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10338 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10339 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10344 * mono_reflection_get_custom_attrs_data_checked:
10345 * @obj: a reflection obj handle
10346 * @error: set on error
10348 * Returns an array of System.Reflection.CustomAttributeData,
10349 * which include information about attributes reflected on
10350 * types loaded using the Reflection Only methods
10353 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10356 MonoCustomAttrInfo *cinfo;
10358 mono_error_init (error);
10360 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10361 return_val_if_nok (error, NULL);
10363 result = mono_custom_attrs_data_construct (cinfo, error);
10364 return_val_if_nok (error, NULL);
10365 if (!cinfo->cached)
10366 mono_custom_attrs_free (cinfo);
10368 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10370 if (mono_loader_get_last_error ())
10371 mono_error_set_from_loader_error (error);
10376 static MonoReflectionType*
10377 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10379 static MonoMethod *method_get_underlying_system_type = NULL;
10380 MonoReflectionType *rt;
10381 MonoMethod *usertype_method;
10383 mono_error_init (error);
10385 if (!method_get_underlying_system_type)
10386 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10388 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10390 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10397 is_corlib_type (MonoClass *klass)
10399 return klass->image == mono_defaults.corlib;
10402 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10403 static MonoClass *cached_class; \
10404 if (cached_class) \
10405 return cached_class == _class; \
10406 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10407 cached_class = _class; \
10414 #ifndef DISABLE_REFLECTION_EMIT
10416 is_sre_array (MonoClass *klass)
10418 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10422 is_sre_byref (MonoClass *klass)
10424 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10428 is_sre_pointer (MonoClass *klass)
10430 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10434 is_sre_generic_instance (MonoClass *klass)
10436 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10440 is_sre_type_builder (MonoClass *klass)
10442 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10446 is_sre_method_builder (MonoClass *klass)
10448 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10452 is_sre_ctor_builder (MonoClass *klass)
10454 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10458 is_sre_field_builder (MonoClass *klass)
10460 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10464 is_sre_method_on_tb_inst (MonoClass *klass)
10466 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10470 is_sre_ctor_on_tb_inst (MonoClass *klass)
10472 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10476 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10479 mono_error_init (error);
10486 if (is_usertype (ref)) {
10487 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10488 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10494 klass = mono_object_class (ref);
10496 if (is_sre_array (klass)) {
10498 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10499 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10500 return_val_if_nok (error, NULL);
10502 if (sre_array->rank == 0) //single dimentional array
10503 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10505 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10506 sre_array->type.type = res;
10508 } else if (is_sre_byref (klass)) {
10510 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10511 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10512 return_val_if_nok (error, NULL);
10514 res = &mono_class_from_mono_type (base)->this_arg;
10515 sre_byref->type.type = res;
10517 } else if (is_sre_pointer (klass)) {
10519 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10520 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10521 return_val_if_nok (error, NULL);
10523 res = &mono_ptr_class_get (base)->byval_arg;
10524 sre_pointer->type.type = res;
10526 } else if (is_sre_generic_instance (klass)) {
10527 MonoType *res, **types;
10528 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10531 count = mono_array_length (gclass->type_arguments);
10532 types = g_new0 (MonoType*, count);
10533 for (i = 0; i < count; ++i) {
10534 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10535 types [i] = mono_reflection_type_get_handle (t, error);
10536 if (!types[i] || !is_ok (error)) {
10542 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10545 gclass->type.type = res;
10549 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10554 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10557 mono_reflection_type_get_handle (type, &error);
10558 mono_error_set_pending_exception (&error);
10562 mono_reflection_register_with_runtime (MonoReflectionType *type)
10565 MonoType *res = mono_reflection_type_get_handle (type, &error);
10566 mono_error_raise_exception (&error); /* FIXME don't raise here */
10567 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10571 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10573 klass = mono_class_from_mono_type (res);
10575 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10576 mono_domain_lock (domain);
10578 if (!image_is_dynamic (klass->image)) {
10579 mono_class_setup_supertypes (klass);
10581 if (!domain->type_hash)
10582 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10583 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10584 mono_g_hash_table_insert (domain->type_hash, res, type);
10586 mono_domain_unlock (domain);
10587 mono_loader_unlock ();
10591 * LOCKING: Assumes the loader lock is held.
10593 static MonoMethodSignature*
10594 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10596 MonoMethodSignature *sig;
10599 count = parameters? mono_array_length (parameters): 0;
10601 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10602 sig->param_count = count;
10603 sig->sentinelpos = -1; /* FIXME */
10604 for (i = 0; i < count; ++i) {
10605 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10606 mono_error_raise_exception (&error); /* FIXME don't raise here */
10612 * LOCKING: Assumes the loader lock is held.
10614 static MonoMethodSignature*
10615 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10616 MonoMethodSignature *sig;
10618 sig = parameters_to_signature (image, ctor->parameters);
10619 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10620 sig->ret = &mono_defaults.void_class->byval_arg;
10625 * LOCKING: Assumes the loader lock is held.
10627 static MonoMethodSignature*
10628 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10630 MonoMethodSignature *sig;
10632 sig = parameters_to_signature (image, method->parameters);
10633 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10634 if (method->rtype) {
10635 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10636 mono_error_raise_exception (&error); /* FIXME don't raise here */
10638 sig->ret = &mono_defaults.void_class->byval_arg;
10640 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10644 static MonoMethodSignature*
10645 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10647 MonoMethodSignature *sig;
10649 sig = parameters_to_signature (NULL, method->parameters);
10650 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10651 if (method->rtype) {
10652 sig->ret = mono_reflection_type_get_handle (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 = 0;
10662 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10665 MonoClass *klass = mono_object_class (prop);
10666 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10667 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10668 *name = mono_string_to_utf8 (pb->name);
10669 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10670 mono_error_raise_exception (&error); /* FIXME don't raise here */
10672 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10673 *name = g_strdup (p->property->name);
10674 if (p->property->get)
10675 *type = mono_method_signature (p->property->get)->ret;
10677 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10682 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10685 MonoClass *klass = mono_object_class (field);
10686 if (strcmp (klass->name, "FieldBuilder") == 0) {
10687 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10688 *name = mono_string_to_utf8 (fb->name);
10689 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10690 mono_error_raise_exception (&error); /* FIXME don't raise here */
10692 MonoReflectionField *f = (MonoReflectionField *)field;
10693 *name = g_strdup (mono_field_get_name (f->field));
10694 *type = f->field->type;
10698 #else /* DISABLE_REFLECTION_EMIT */
10701 mono_reflection_register_with_runtime (MonoReflectionType *type)
10703 /* This is empty */
10707 is_sre_type_builder (MonoClass *klass)
10713 is_sre_generic_instance (MonoClass *klass)
10719 init_type_builder_generics (MonoObject *type)
10723 #endif /* !DISABLE_REFLECTION_EMIT */
10727 is_sr_mono_field (MonoClass *klass)
10729 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10733 is_sr_mono_property (MonoClass *klass)
10735 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10739 is_sr_mono_method (MonoClass *klass)
10741 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10745 is_sr_mono_cmethod (MonoClass *klass)
10747 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10751 is_sr_mono_generic_method (MonoClass *klass)
10753 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10757 is_sr_mono_generic_cmethod (MonoClass *klass)
10759 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10763 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10765 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10769 is_usertype (MonoReflectionType *ref)
10771 MonoClass *klass = mono_object_class (ref);
10772 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10775 static MonoReflectionType*
10776 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10778 mono_error_init (error);
10779 if (!type || type->type)
10782 if (is_usertype (type)) {
10783 type = mono_reflection_type_get_underlying_system_type (type, error);
10784 return_val_if_nok (error, NULL);
10785 if (is_usertype (type)) {
10786 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10794 * Encode a value in a custom attribute stream of bytes.
10795 * The value to encode is either supplied as an object in argument val
10796 * (valuetypes are boxed), or as a pointer to the data in the
10798 * @type represents the type of the value
10799 * @buffer is the start of the buffer
10800 * @p the current position in the buffer
10801 * @buflen contains the size of the buffer and is used to return the new buffer size
10802 * if this needs to be realloced.
10803 * @retbuffer and @retp return the start and the position of the buffer
10806 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10809 MonoTypeEnum simple_type;
10811 if ((p-buffer) + 10 >= *buflen) {
10814 newbuf = (char *)g_realloc (buffer, *buflen);
10815 p = newbuf + (p-buffer);
10819 argval = ((char*)arg + sizeof (MonoObject));
10820 simple_type = type->type;
10822 switch (simple_type) {
10823 case MONO_TYPE_BOOLEAN:
10828 case MONO_TYPE_CHAR:
10831 swap_with_size (p, argval, 2, 1);
10837 swap_with_size (p, argval, 4, 1);
10841 swap_with_size (p, argval, 8, 1);
10846 swap_with_size (p, argval, 8, 1);
10849 case MONO_TYPE_VALUETYPE:
10850 if (type->data.klass->enumtype) {
10851 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10854 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10857 case MONO_TYPE_STRING: {
10864 str = mono_string_to_utf8 ((MonoString*)arg);
10865 slen = strlen (str);
10866 if ((p-buffer) + 10 + slen >= *buflen) {
10870 newbuf = (char *)g_realloc (buffer, *buflen);
10871 p = newbuf + (p-buffer);
10874 mono_metadata_encode_value (slen, p, &p);
10875 memcpy (p, str, slen);
10880 case MONO_TYPE_CLASS: {
10883 MonoType *arg_type;
10889 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10890 mono_error_raise_exception (&error); /* FIXME don't raise here */
10891 str = type_get_qualified_name (arg_type, NULL);
10892 slen = strlen (str);
10893 if ((p-buffer) + 10 + slen >= *buflen) {
10897 newbuf = (char *)g_realloc (buffer, *buflen);
10898 p = newbuf + (p-buffer);
10901 mono_metadata_encode_value (slen, p, &p);
10902 memcpy (p, str, slen);
10907 case MONO_TYPE_SZARRAY: {
10909 MonoClass *eclass, *arg_eclass;
10912 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10915 len = mono_array_length ((MonoArray*)arg);
10917 *p++ = (len >> 8) & 0xff;
10918 *p++ = (len >> 16) & 0xff;
10919 *p++ = (len >> 24) & 0xff;
10921 *retbuffer = buffer;
10922 eclass = type->data.klass;
10923 arg_eclass = mono_object_class (arg)->element_class;
10926 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10927 eclass = mono_defaults.object_class;
10929 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10930 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10931 int elsize = mono_class_array_element_size (arg_eclass);
10932 for (i = 0; i < len; ++i) {
10933 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10936 } else if (eclass->valuetype && arg_eclass->valuetype) {
10937 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10938 int elsize = mono_class_array_element_size (eclass);
10939 for (i = 0; i < len; ++i) {
10940 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10944 for (i = 0; i < len; ++i) {
10945 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10950 case MONO_TYPE_OBJECT: {
10956 * The parameter type is 'object' but the type of the actual
10957 * argument is not. So we have to add type information to the blob
10958 * too. This is completely undocumented in the spec.
10962 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10967 klass = mono_object_class (arg);
10969 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10972 } else if (klass->enumtype) {
10974 } else if (klass == mono_defaults.string_class) {
10975 simple_type = MONO_TYPE_STRING;
10978 } else if (klass->rank == 1) {
10980 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10981 /* See Partition II, Appendix B3 */
10984 *p++ = klass->element_class->byval_arg.type;
10985 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10987 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10988 *p++ = simple_type = klass->byval_arg.type;
10991 g_error ("unhandled type in custom attr");
10993 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10994 slen = strlen (str);
10995 if ((p-buffer) + 10 + slen >= *buflen) {
10999 newbuf = (char *)g_realloc (buffer, *buflen);
11000 p = newbuf + (p-buffer);
11003 mono_metadata_encode_value (slen, p, &p);
11004 memcpy (p, str, slen);
11007 simple_type = mono_class_enum_basetype (klass)->type;
11011 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11014 *retbuffer = buffer;
11018 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11020 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11021 char *str = type_get_qualified_name (type, NULL);
11022 int slen = strlen (str);
11026 * This seems to be optional...
11029 mono_metadata_encode_value (slen, p, &p);
11030 memcpy (p, str, slen);
11033 } else if (type->type == MONO_TYPE_OBJECT) {
11035 } else if (type->type == MONO_TYPE_CLASS) {
11036 /* it should be a type: encode_cattr_value () has the check */
11039 mono_metadata_encode_value (type->type, p, &p);
11040 if (type->type == MONO_TYPE_SZARRAY)
11041 /* See the examples in Partition VI, Annex B */
11042 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11048 #ifndef DISABLE_REFLECTION_EMIT
11050 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11053 /* Preallocate a large enough buffer */
11054 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11055 char *str = type_get_qualified_name (type, NULL);
11056 len = strlen (str);
11058 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11059 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11060 len = strlen (str);
11065 len += strlen (name);
11067 if ((p-buffer) + 20 + len >= *buflen) {
11071 newbuf = (char *)g_realloc (buffer, *buflen);
11072 p = newbuf + (p-buffer);
11076 encode_field_or_prop_type (type, p, &p);
11078 len = strlen (name);
11079 mono_metadata_encode_value (len, p, &p);
11080 memcpy (p, name, len);
11082 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11084 *retbuffer = buffer;
11088 * mono_reflection_get_custom_attrs_blob:
11089 * @ctor: custom attribute constructor
11090 * @ctorArgs: arguments o the constructor
11096 * Creates the blob of data that needs to be saved in the metadata and that represents
11097 * the custom attributed described by @ctor, @ctorArgs etc.
11098 * Returns: a Byte array representing the blob of data.
11101 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11104 MonoMethodSignature *sig;
11109 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11110 /* sig is freed later so allocate it in the heap */
11111 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11113 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11116 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11118 p = buffer = (char *)g_malloc (buflen);
11119 /* write the prolog */
11122 for (i = 0; i < sig->param_count; ++i) {
11123 arg = mono_array_get (ctorArgs, MonoObject*, i);
11124 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11128 i += mono_array_length (properties);
11130 i += mono_array_length (fields);
11132 *p++ = (i >> 8) & 0xff;
11135 for (i = 0; i < mono_array_length (properties); ++i) {
11139 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11140 get_prop_name_and_type (prop, &pname, &ptype);
11141 *p++ = 0x54; /* PROPERTY signature */
11142 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11149 for (i = 0; i < mono_array_length (fields); ++i) {
11153 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11154 get_field_name_and_type (field, &fname, &ftype);
11155 *p++ = 0x53; /* FIELD signature */
11156 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11161 g_assert (p - buffer <= buflen);
11162 buflen = p - buffer;
11163 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11164 p = mono_array_addr (result, char, 0);
11165 memcpy (p, buffer, buflen);
11167 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11173 * mono_reflection_setup_internal_class:
11174 * @tb: a TypeBuilder object
11176 * Creates a MonoClass that represents the TypeBuilder.
11177 * This is a trick that lets us simplify a lot of reflection code
11178 * (and will allow us to support Build and Run assemblies easier).
11181 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11184 MonoClass *klass, *parent;
11186 RESOLVE_TYPE (tb->parent, &error);
11187 mono_error_raise_exception (&error); /* FIXME don't raise here */
11189 mono_loader_lock ();
11192 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11193 if (!is_ok (&error)) {
11194 mono_loader_unlock ();
11195 mono_error_raise_exception (&error); /* FIXME don't raise here */
11197 /* check so we can compile corlib correctly */
11198 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11199 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11200 parent = parent_type->data.klass;
11202 parent = mono_class_from_mono_type (parent_type);
11208 /* the type has already being created: it means we just have to change the parent */
11209 if (tb->type.type) {
11210 klass = mono_class_from_mono_type (tb->type.type);
11211 klass->parent = NULL;
11212 /* fool mono_class_setup_parent */
11213 klass->supertypes = NULL;
11214 mono_class_setup_parent (klass, parent);
11215 mono_class_setup_mono_type (klass);
11216 mono_loader_unlock ();
11220 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11222 klass->image = &tb->module->dynamic_image->image;
11224 klass->inited = 1; /* we lie to the runtime */
11225 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11226 if (!mono_error_ok (&error))
11228 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11229 if (!mono_error_ok (&error))
11231 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11232 klass->flags = tb->attrs;
11234 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11236 klass->element_class = klass;
11238 if (mono_class_get_ref_info (klass) == NULL) {
11240 mono_class_set_ref_info (klass, tb);
11242 /* Put into cache so mono_class_get_checked () will find it.
11243 Skip nested types as those should not be available on the global scope. */
11244 if (!tb->nesting_type)
11245 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11248 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11249 by performing a mono_class_get which does the full resolution.
11251 Working around this semantics would require us to write a lot of code for no clear advantage.
11253 mono_image_append_class_to_reflection_info_set (klass);
11255 g_assert (mono_class_get_ref_info (klass) == tb);
11258 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11260 if (parent != NULL) {
11261 mono_class_setup_parent (klass, parent);
11262 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11263 const char *old_n = klass->name;
11264 /* trick to get relative numbering right when compiling corlib */
11265 klass->name = "BuildingObject";
11266 mono_class_setup_parent (klass, mono_defaults.object_class);
11267 klass->name = old_n;
11270 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11271 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11272 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11273 klass->instance_size = sizeof (MonoObject);
11274 klass->size_inited = 1;
11275 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11278 mono_class_setup_mono_type (klass);
11280 mono_class_setup_supertypes (klass);
11283 * FIXME: handle interfaces.
11286 tb->type.type = &klass->byval_arg;
11288 if (tb->nesting_type) {
11289 g_assert (tb->nesting_type->type);
11290 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11291 if (!is_ok (&error)) goto failure;
11292 klass->nested_in = mono_class_from_mono_type (nesting_type);
11295 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11297 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11299 mono_loader_unlock ();
11303 mono_loader_unlock ();
11304 mono_error_raise_exception (&error);
11308 * mono_reflection_setup_generic_class:
11309 * @tb: a TypeBuilder object
11311 * Setup the generic class before adding the first generic parameter.
11314 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11319 * mono_reflection_create_generic_class:
11320 * @tb: a TypeBuilder object
11322 * Creates the generic class after all generic parameters have been added.
11325 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11331 klass = mono_class_from_mono_type (tb->type.type);
11333 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11335 if (klass->generic_container || (count == 0))
11338 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11340 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11342 klass->generic_container->owner.klass = klass;
11343 klass->generic_container->type_argc = count;
11344 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11346 klass->is_generic = 1;
11348 for (i = 0; i < count; i++) {
11349 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11350 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11351 mono_error_raise_exception (&error); /* FIXME don't raise here */
11352 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11353 klass->generic_container->type_params [i] = *param;
11354 /*Make sure we are a diferent type instance */
11355 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11356 klass->generic_container->type_params [i].info.pklass = NULL;
11357 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11359 g_assert (klass->generic_container->type_params [i].param.owner);
11362 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11366 * mono_reflection_create_internal_class:
11367 * @tb: a TypeBuilder object
11369 * Actually create the MonoClass that is associated with the TypeBuilder.
11372 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11377 klass = mono_class_from_mono_type (tb->type.type);
11379 mono_loader_lock ();
11380 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11381 MonoReflectionFieldBuilder *fb;
11383 MonoType *enum_basetype;
11385 g_assert (tb->fields != NULL);
11386 g_assert (mono_array_length (tb->fields) >= 1);
11388 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11390 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11391 if (!is_ok (&error)) {
11392 mono_loader_unlock ();
11393 mono_error_raise_exception (&error); /* FIXME don't raise here */
11395 if (!mono_type_is_valid_enum_basetype (field_type)) {
11396 mono_loader_unlock ();
11400 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11401 if (!is_ok (&error)) {
11402 mono_loader_unlock ();
11403 mono_error_raise_exception (&error); /* FIXME don't raise here */
11405 klass->element_class = mono_class_from_mono_type (enum_basetype);
11406 if (!klass->element_class)
11407 klass->element_class = mono_class_from_mono_type (enum_basetype);
11410 * get the element_class from the current corlib.
11412 ec = default_class_from_mono_type (enum_basetype);
11413 klass->instance_size = ec->instance_size;
11414 klass->size_inited = 1;
11416 * this is almost safe to do with enums and it's needed to be able
11417 * to create objects of the enum type (for use in SetConstant).
11419 /* FIXME: Does this mean enums can't have method overrides ? */
11420 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11422 mono_loader_unlock ();
11425 static MonoMarshalSpec*
11426 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11427 MonoReflectionMarshal *minfo)
11430 MonoMarshalSpec *res;
11432 res = image_g_new0 (image, MonoMarshalSpec, 1);
11433 res->native = (MonoMarshalNative)minfo->type;
11435 switch (minfo->type) {
11436 case MONO_NATIVE_LPARRAY:
11437 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11438 if (minfo->has_size) {
11439 res->data.array_data.param_num = minfo->param_num;
11440 res->data.array_data.num_elem = minfo->count;
11441 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11444 res->data.array_data.param_num = -1;
11445 res->data.array_data.num_elem = -1;
11446 res->data.array_data.elem_mult = -1;
11450 case MONO_NATIVE_BYVALTSTR:
11451 case MONO_NATIVE_BYVALARRAY:
11452 res->data.array_data.num_elem = minfo->count;
11455 case MONO_NATIVE_CUSTOM:
11456 if (minfo->marshaltyperef) {
11457 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11458 mono_error_raise_exception (&error); /* FIXME don't raise here */
11459 res->data.custom_data.custom_name =
11460 type_get_fully_qualified_name (marshaltyperef);
11462 if (minfo->mcookie)
11463 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11472 #endif /* !DISABLE_REFLECTION_EMIT */
11474 MonoReflectionMarshalAsAttribute*
11475 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11476 MonoMarshalSpec *spec, MonoError *error)
11478 MonoReflectionType *rt;
11479 MonoReflectionMarshalAsAttribute *minfo;
11482 mono_error_init (error);
11484 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11487 minfo->utype = spec->native;
11489 switch (minfo->utype) {
11490 case MONO_NATIVE_LPARRAY:
11491 minfo->array_subtype = spec->data.array_data.elem_type;
11492 minfo->size_const = spec->data.array_data.num_elem;
11493 if (spec->data.array_data.param_num != -1)
11494 minfo->size_param_index = spec->data.array_data.param_num;
11497 case MONO_NATIVE_BYVALTSTR:
11498 case MONO_NATIVE_BYVALARRAY:
11499 minfo->size_const = spec->data.array_data.num_elem;
11502 case MONO_NATIVE_CUSTOM:
11503 if (spec->data.custom_data.custom_name) {
11504 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11506 rt = mono_type_get_object_checked (domain, mtype, error);
11510 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11513 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11515 if (spec->data.custom_data.cookie)
11516 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11526 #ifndef DISABLE_REFLECTION_EMIT
11528 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11529 ReflectionMethodBuilder *rmb,
11530 MonoMethodSignature *sig)
11534 MonoMethodWrapper *wrapperm;
11535 MonoMarshalSpec **specs;
11536 MonoReflectionMethodAux *method_aux;
11541 mono_error_init (&error);
11543 * Methods created using a MethodBuilder should have their memory allocated
11544 * inside the image mempool, while dynamic methods should have their memory
11547 dynamic = rmb->refs != NULL;
11548 image = dynamic ? NULL : klass->image;
11551 g_assert (!klass->generic_class);
11553 mono_loader_lock ();
11555 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11556 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11557 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11559 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11561 wrapperm = (MonoMethodWrapper*)m;
11563 m->dynamic = dynamic;
11565 m->flags = rmb->attrs;
11566 m->iflags = rmb->iattrs;
11567 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11569 m->signature = sig;
11570 m->sre_method = TRUE;
11571 m->skip_visibility = rmb->skip_visibility;
11572 if (rmb->table_idx)
11573 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11575 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11576 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11577 m->string_ctor = 1;
11579 m->signature->pinvoke = 1;
11580 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11581 m->signature->pinvoke = 1;
11583 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11585 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11586 g_assert (mono_error_ok (&error));
11587 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11588 g_assert (mono_error_ok (&error));
11590 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11592 if (image_is_dynamic (klass->image))
11593 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11595 mono_loader_unlock ();
11598 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11599 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11600 MonoMethodHeader *header;
11602 gint32 max_stack, i;
11603 gint32 num_locals = 0;
11604 gint32 num_clauses = 0;
11608 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11609 code_size = rmb->ilgen->code_len;
11610 max_stack = rmb->ilgen->max_stack;
11611 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11612 if (rmb->ilgen->ex_handlers)
11613 num_clauses = method_count_clauses (rmb->ilgen);
11616 code = mono_array_addr (rmb->code, guint8, 0);
11617 code_size = mono_array_length (rmb->code);
11618 /* we probably need to run a verifier on the code... */
11628 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11629 header->code_size = code_size;
11630 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11631 memcpy ((char*)header->code, code, code_size);
11632 header->max_stack = max_stack;
11633 header->init_locals = rmb->init_locals;
11634 header->num_locals = num_locals;
11636 for (i = 0; i < num_locals; ++i) {
11637 MonoReflectionLocalBuilder *lb =
11638 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11640 header->locals [i] = image_g_new0 (image, MonoType, 1);
11641 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11642 mono_error_assert_ok (&error);
11643 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11646 header->num_clauses = num_clauses;
11648 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11649 rmb->ilgen, num_clauses, &error);
11650 mono_error_assert_ok (&error);
11653 wrapperm->header = header;
11656 if (rmb->generic_params) {
11657 int count = mono_array_length (rmb->generic_params);
11658 MonoGenericContainer *container = rmb->generic_container;
11660 g_assert (container);
11662 container->type_argc = count;
11663 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11664 container->owner.method = m;
11665 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11667 m->is_generic = TRUE;
11668 mono_method_set_generic_container (m, container);
11670 for (i = 0; i < count; i++) {
11671 MonoReflectionGenericParam *gp =
11672 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11673 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11674 mono_error_assert_ok (&error);
11675 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11676 container->type_params [i] = *param;
11680 * The method signature might have pointers to generic parameters that belong to other methods.
11681 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11682 * generic parameters.
11684 for (i = 0; i < m->signature->param_count; ++i) {
11685 MonoType *t = m->signature->params [i];
11686 if (t->type == MONO_TYPE_MVAR) {
11687 MonoGenericParam *gparam = t->data.generic_param;
11688 if (gparam->num < count) {
11689 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11690 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11696 if (klass->generic_container) {
11697 container->parent = klass->generic_container;
11698 container->context.class_inst = klass->generic_container->context.class_inst;
11700 container->context.method_inst = mono_get_shared_generic_inst (container);
11704 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11708 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11710 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11711 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11712 for (i = 0; i < rmb->nrefs; ++i)
11713 data [i + 1] = rmb->refs [i];
11718 /* Parameter info */
11721 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11722 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11723 for (i = 0; i <= m->signature->param_count; ++i) {
11724 MonoReflectionParamBuilder *pb;
11725 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11726 if ((i > 0) && (pb->attrs)) {
11727 /* Make a copy since it might point to a shared type structure */
11728 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11729 m->signature->params [i - 1]->attrs = pb->attrs;
11732 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11733 MonoDynamicImage *assembly;
11735 MonoTypeEnum def_type;
11739 if (!method_aux->param_defaults) {
11740 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11741 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11743 assembly = (MonoDynamicImage*)klass->image;
11744 idx = encode_constant (assembly, pb->def_value, &def_type);
11745 /* Copy the data from the blob since it might get realloc-ed */
11746 p = assembly->blob.data + idx;
11747 len = mono_metadata_decode_blob_size (p, &p2);
11749 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11750 method_aux->param_default_types [i] = def_type;
11751 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11755 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11756 g_assert (mono_error_ok (&error));
11759 if (!method_aux->param_cattr)
11760 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11761 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11767 /* Parameter marshalling */
11770 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11771 MonoReflectionParamBuilder *pb;
11772 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11773 if (pb->marshal_info) {
11775 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11776 specs [pb->position] =
11777 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11781 if (specs != NULL) {
11783 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11784 method_aux->param_marshall = specs;
11787 if (image_is_dynamic (klass->image) && method_aux)
11788 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11790 mono_loader_unlock ();
11796 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11798 ReflectionMethodBuilder rmb;
11799 MonoMethodSignature *sig;
11801 mono_loader_lock ();
11802 sig = ctor_builder_to_signature (klass->image, mb);
11803 mono_loader_unlock ();
11805 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11808 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11809 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11811 /* If we are in a generic class, we might be called multiple times from inflate_method */
11812 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11813 /* ilgen is no longer needed */
11817 return mb->mhandle;
11821 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11823 ReflectionMethodBuilder rmb;
11824 MonoMethodSignature *sig;
11826 mono_error_init (error);
11828 mono_loader_lock ();
11829 sig = method_builder_to_signature (klass->image, mb);
11830 mono_loader_unlock ();
11832 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11835 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11836 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11838 /* If we are in a generic class, we might be called multiple times from inflate_method */
11839 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11840 /* ilgen is no longer needed */
11843 return mb->mhandle;
11846 static MonoClassField*
11847 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11849 MonoClassField *field;
11853 field = g_new0 (MonoClassField, 1);
11855 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11856 g_assert (mono_error_ok (&error));
11857 if (fb->attrs || fb->modreq || fb->modopt) {
11858 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11859 if (!is_ok (&error)) {
11861 mono_error_raise_exception (&error); /* FIXME don't raise here */
11863 field->type = mono_metadata_type_dup (NULL, type);
11864 field->type->attrs = fb->attrs;
11866 g_assert (image_is_dynamic (klass->image));
11867 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
11868 g_free (field->type);
11869 if (!is_ok (&error)) {
11871 mono_error_raise_exception (&error); /* FIXME don't raise here */
11873 field->type = mono_metadata_type_dup (klass->image, custom);
11876 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11877 if (!is_ok (&error)) {
11879 mono_error_raise_exception (&error); /* FIXME don't raise here */
11882 if (fb->offset != -1)
11883 field->offset = fb->offset;
11884 field->parent = klass;
11885 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11887 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11894 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11898 MonoReflectionTypeBuilder *tb = NULL;
11899 gboolean is_dynamic = FALSE;
11900 MonoClass *geninst;
11902 mono_loader_lock ();
11904 if (is_sre_type_builder (mono_object_class (type))) {
11905 tb = (MonoReflectionTypeBuilder *) type;
11908 } else if (is_sre_generic_instance (mono_object_class (type))) {
11909 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11910 MonoReflectionType *gtd = rgi->generic_type;
11912 if (is_sre_type_builder (mono_object_class (gtd))) {
11913 tb = (MonoReflectionTypeBuilder *)gtd;
11918 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11919 if (tb && tb->generic_container)
11920 mono_reflection_create_generic_class (tb);
11922 MonoType *t = mono_reflection_type_get_handle (type, &error);
11923 mono_error_raise_exception (&error); /* FIXME don't raise here */
11925 klass = mono_class_from_mono_type (t);
11926 if (!klass->generic_container) {
11927 mono_loader_unlock ();
11931 if (klass->wastypebuilder) {
11932 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11937 mono_loader_unlock ();
11939 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11941 return &geninst->byval_arg;
11945 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11947 MonoGenericClass *gclass;
11948 MonoGenericInst *inst;
11950 g_assert (klass->generic_container);
11952 inst = mono_metadata_get_generic_inst (type_argc, types);
11953 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11955 return mono_generic_class_get_class (gclass);
11958 MonoReflectionMethod*
11959 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11963 MonoMethod *method, *inflated;
11964 MonoMethodInflated *imethod;
11965 MonoGenericContext tmp_context;
11966 MonoGenericInst *ginst;
11967 MonoType **type_argv;
11970 /*FIXME but this no longer should happen*/
11971 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11972 #ifndef DISABLE_REFLECTION_EMIT
11973 MonoReflectionMethodBuilder *mb = NULL;
11977 mb = (MonoReflectionMethodBuilder *) rmethod;
11978 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11979 mono_error_raise_exception (&error); /* FIXME don't raise here */
11980 klass = mono_class_from_mono_type (tb);
11982 method = methodbuilder_to_mono_method (klass, mb, &error);
11984 mono_error_raise_exception (&error); /* FIXME don't raise here */
11986 g_assert_not_reached ();
11990 method = rmethod->method;
11993 klass = method->klass;
11995 if (method->is_inflated)
11996 method = ((MonoMethodInflated *) method)->declaring;
11998 count = mono_method_signature (method)->generic_param_count;
11999 if (count != mono_array_length (types))
12002 type_argv = g_new0 (MonoType *, count);
12003 for (i = 0; i < count; i++) {
12004 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12005 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12006 if (!is_ok (&error)) {
12007 g_free (type_argv);
12008 mono_error_raise_exception (&error); /* FIXME don't raise here */
12011 ginst = mono_metadata_get_generic_inst (count, type_argv);
12012 g_free (type_argv);
12014 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12015 tmp_context.method_inst = ginst;
12017 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12018 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12019 imethod = (MonoMethodInflated *) inflated;
12021 /*FIXME but I think this is no longer necessary*/
12022 if (image_is_dynamic (method->klass->image)) {
12023 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12025 * This table maps metadata structures representing inflated methods/fields
12026 * to the reflection objects representing their generic definitions.
12028 mono_image_lock ((MonoImage*)image);
12029 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12030 mono_image_unlock ((MonoImage*)image);
12033 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12034 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12036 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12037 mono_error_raise_exception (&error); /* FIXME don't raise here */
12041 #ifndef DISABLE_REFLECTION_EMIT
12043 static MonoMethod *
12044 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12046 MonoMethodInflated *imethod;
12047 MonoGenericContext *context;
12051 * With generic code sharing the klass might not be inflated.
12052 * This can happen because classes inflated with their own
12053 * type arguments are "normalized" to the uninflated class.
12055 if (!klass->generic_class)
12058 context = mono_class_get_context (klass);
12060 if (klass->method.count && klass->methods) {
12061 /* Find the already created inflated method */
12062 for (i = 0; i < klass->method.count; ++i) {
12063 g_assert (klass->methods [i]->is_inflated);
12064 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12067 g_assert (i < klass->method.count);
12068 imethod = (MonoMethodInflated*)klass->methods [i];
12071 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12072 mono_error_assert_ok (&error);
12075 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12076 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12078 mono_image_lock ((MonoImage*)image);
12079 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12080 mono_image_unlock ((MonoImage*)image);
12082 return (MonoMethod *) imethod;
12085 static MonoMethod *
12086 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12088 MonoMethod *method;
12091 mono_error_init (error);
12093 MonoClass *type_class = mono_object_class (type);
12095 if (is_sre_generic_instance (type_class)) {
12096 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12097 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12098 return_val_if_nok (error, NULL);
12099 gklass = mono_class_from_mono_type (generic_type);
12100 } else if (is_sre_type_builder (type_class)) {
12101 MonoType *t = mono_reflection_type_get_handle (type, error);
12102 return_val_if_nok (error, NULL);
12103 gklass = mono_class_from_mono_type (t);
12104 } else if (type->type) {
12105 gklass = mono_class_from_mono_type (type->type);
12106 gklass = mono_class_get_generic_type_definition (gklass);
12108 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12111 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12112 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12113 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12115 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12119 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12120 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12123 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12124 method = ((MonoReflectionMethod *) obj)->method;
12126 method = NULL; /* prevent compiler warning */
12127 g_error ("can't handle type %s", obj->vtable->klass->name);
12130 MonoType *t = mono_reflection_type_get_handle (type, error);
12131 return_val_if_nok (error, NULL);
12132 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12135 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12137 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12140 MonoGenericClass *gclass;
12141 MonoDynamicGenericClass *dgclass;
12142 MonoClass *klass, *gklass;
12146 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12147 mono_error_raise_exception (&error); /* FIXME don't raise here */
12148 klass = mono_class_from_mono_type (gtype);
12149 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12150 gclass = gtype->data.generic_class;
12152 if (!gclass->is_dynamic)
12155 dgclass = (MonoDynamicGenericClass *) gclass;
12157 if (dgclass->initialized)
12160 gklass = gclass->container_class;
12161 mono_class_init (gklass);
12163 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12165 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12166 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12167 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12169 for (i = 0; i < dgclass->count_fields; i++) {
12171 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12172 MonoClassField *field, *inflated_field = NULL;
12174 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12175 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12176 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12177 field = ((MonoReflectionField *) obj)->field;
12179 field = NULL; /* prevent compiler warning */
12180 g_assert_not_reached ();
12183 dgclass->fields [i] = *field;
12184 dgclass->fields [i].parent = klass;
12185 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12186 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12187 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12188 dgclass->field_generic_types [i] = field->type;
12189 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12190 dgclass->field_objects [i] = obj;
12192 if (inflated_field) {
12193 g_free (inflated_field);
12195 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12199 dgclass->initialized = TRUE;
12203 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12205 MonoDynamicGenericClass *dgclass;
12208 g_assert (gclass->is_dynamic);
12210 dgclass = (MonoDynamicGenericClass *)gclass;
12212 for (i = 0; i < dgclass->count_fields; ++i) {
12213 MonoClassField *field = dgclass->fields + i;
12214 mono_metadata_free_type (field->type);
12215 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12220 fix_partial_generic_class (MonoClass *klass)
12222 MonoClass *gklass = klass->generic_class->container_class;
12223 MonoDynamicGenericClass *dgclass;
12226 if (klass->wastypebuilder)
12229 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12230 if (klass->parent != gklass->parent) {
12232 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12233 if (mono_error_ok (&error)) {
12234 MonoClass *parent = mono_class_from_mono_type (parent_type);
12235 mono_metadata_free_type (parent_type);
12236 if (parent != klass->parent) {
12237 /*fool mono_class_setup_parent*/
12238 klass->supertypes = NULL;
12239 mono_class_setup_parent (klass, parent);
12242 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12243 mono_error_cleanup (&error);
12244 if (gklass->wastypebuilder)
12245 klass->wastypebuilder = TRUE;
12250 if (!dgclass->initialized)
12253 if (klass->method.count != gklass->method.count) {
12254 klass->method.count = gklass->method.count;
12255 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12257 for (i = 0; i < klass->method.count; i++) {
12259 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12260 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12261 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12265 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12266 klass->interface_count = gklass->interface_count;
12267 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12268 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12270 for (i = 0; i < gklass->interface_count; ++i) {
12272 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12273 mono_error_raise_exception (&error); /* FIXME don't raise here */
12275 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12276 mono_metadata_free_type (iface_type);
12278 ensure_runtime_vtable (klass->interfaces [i], &error);
12279 mono_error_raise_exception (&error); /* FIXME don't raise here */
12281 klass->interfaces_inited = 1;
12284 if (klass->field.count != gklass->field.count) {
12285 klass->field.count = gklass->field.count;
12286 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12288 for (i = 0; i < klass->field.count; i++) {
12290 klass->fields [i] = gklass->fields [i];
12291 klass->fields [i].parent = klass;
12292 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12293 mono_error_raise_exception (&error); /* FIXME don't raise here */
12297 /*We can only finish with this klass once it's parent has as well*/
12298 if (gklass->wastypebuilder)
12299 klass->wastypebuilder = TRUE;
12304 * ensure_generic_class_runtime_vtable:
12305 * @klass a generic class
12306 * @error set on error
12308 * Ensures that the generic container of @klass has a vtable and
12309 * returns TRUE on success. On error returns FALSE and sets @error.
12312 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12314 MonoClass *gklass = klass->generic_class->container_class;
12316 mono_error_init (error);
12318 if (!ensure_runtime_vtable (gklass, error))
12321 fix_partial_generic_class (klass);
12327 * ensure_runtime_vtable:
12329 * @error set on error
12331 * Ensures that @klass has a vtable and returns TRUE on success. On
12332 * error returns FALSE and sets @error.
12335 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12337 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12340 mono_error_init (error);
12342 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12345 if (!ensure_runtime_vtable (klass->parent, error))
12349 num = tb->ctors? mono_array_length (tb->ctors): 0;
12350 num += tb->num_methods;
12351 klass->method.count = num;
12352 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12353 num = tb->ctors? mono_array_length (tb->ctors): 0;
12354 for (i = 0; i < num; ++i) {
12355 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12358 klass->methods [i] = ctor;
12360 num = tb->num_methods;
12362 for (i = 0; i < num; ++i) {
12363 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12366 klass->methods [j++] = meth;
12369 if (tb->interfaces) {
12370 klass->interface_count = mono_array_length (tb->interfaces);
12371 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12372 for (i = 0; i < klass->interface_count; ++i) {
12373 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12374 return_val_if_nok (error, FALSE);
12375 klass->interfaces [i] = mono_class_from_mono_type (iface);
12376 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12379 klass->interfaces_inited = 1;
12381 } else if (klass->generic_class){
12382 if (!ensure_generic_class_runtime_vtable (klass, error))
12386 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12388 for (i = 0; i < klass->method.count; ++i) {
12389 MonoMethod *im = klass->methods [i];
12390 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12391 im->slot = slot_num++;
12394 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12395 mono_class_setup_interface_offsets (klass);
12396 mono_class_setup_interface_id (klass);
12400 * The generic vtable is needed even if image->run is not set since some
12401 * runtime code like ves_icall_Type_GetMethodsByName depends on
12402 * method->slot being defined.
12406 * tb->methods could not be freed since it is used for determining
12407 * overrides during dynamic vtable construction.
12414 mono_reflection_method_get_handle (MonoObject *method)
12417 MonoClass *klass = mono_object_class (method);
12418 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12419 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12420 return sr_method->method;
12422 if (is_sre_method_builder (klass)) {
12423 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12424 return mb->mhandle;
12426 if (is_sre_method_on_tb_inst (klass)) {
12427 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12428 MonoMethod *result;
12429 /*FIXME move this to a proper method and unify with resolve_object*/
12430 if (m->method_args) {
12431 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12432 mono_error_raise_exception (&error); /* FIXME don't raise here */
12434 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12435 mono_error_raise_exception (&error); /* FIXME don't raise here */
12436 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12437 MonoMethod *mono_method;
12439 if (is_sre_method_builder (mono_object_class (m->mb)))
12440 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12441 else if (is_sr_mono_method (mono_object_class (m->mb)))
12442 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12444 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)));
12446 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12451 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12456 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12458 MonoReflectionTypeBuilder *tb;
12460 MonoReflectionMethod *m;
12463 *num_overrides = 0;
12465 g_assert (image_is_dynamic (klass->image));
12467 if (!mono_class_get_ref_info (klass))
12470 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12472 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12476 for (i = 0; i < tb->num_methods; ++i) {
12477 MonoReflectionMethodBuilder *mb =
12478 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12479 if (mb->override_methods)
12480 onum += mono_array_length (mb->override_methods);
12485 *overrides = g_new0 (MonoMethod*, onum * 2);
12488 for (i = 0; i < tb->num_methods; ++i) {
12489 MonoReflectionMethodBuilder *mb =
12490 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12491 if (mb->override_methods) {
12492 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12493 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12495 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12496 (*overrides) [onum * 2 + 1] = mb->mhandle;
12498 g_assert (mb->mhandle);
12506 *num_overrides = onum;
12510 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12512 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12513 MonoReflectionFieldBuilder *fb;
12514 MonoClassField *field;
12515 MonoImage *image = klass->image;
12516 const char *p, *p2;
12518 guint32 len, idx, real_size = 0;
12520 klass->field.count = tb->num_fields;
12521 klass->field.first = 0;
12523 mono_error_init (error);
12525 if (tb->class_size) {
12526 if ((tb->packing_size & 0xffffff00) != 0) {
12527 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12528 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12531 klass->packing_size = tb->packing_size;
12532 real_size = klass->instance_size + tb->class_size;
12535 if (!klass->field.count) {
12536 klass->instance_size = MAX (klass->instance_size, real_size);
12540 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12541 mono_class_alloc_ext (klass);
12542 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12544 This is, guess what, a hack.
12545 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12546 On the static path no field class is resolved, only types are built. This is the right thing to do
12548 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12550 klass->size_inited = 1;
12552 for (i = 0; i < klass->field.count; ++i) {
12553 MonoArray *rva_data;
12554 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12555 field = &klass->fields [i];
12556 field->name = mono_string_to_utf8_image (image, fb->name, error);
12557 if (!mono_error_ok (error))
12560 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12561 return_if_nok (error);
12562 field->type = mono_metadata_type_dup (klass->image, type);
12563 field->type->attrs = fb->attrs;
12565 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12566 return_if_nok (error);
12569 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12570 char *base = mono_array_addr (rva_data, char, 0);
12571 size_t size = mono_array_length (rva_data);
12572 char *data = (char *)mono_image_alloc (klass->image, size);
12573 memcpy (data, base, size);
12574 klass->ext->field_def_values [i].data = data;
12576 if (fb->offset != -1)
12577 field->offset = fb->offset;
12578 field->parent = klass;
12579 fb->handle = field;
12580 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12582 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12583 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12585 if (fb->def_value) {
12586 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12587 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12588 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12589 /* Copy the data from the blob since it might get realloc-ed */
12590 p = assembly->blob.data + idx;
12591 len = mono_metadata_decode_blob_size (p, &p2);
12593 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12594 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12598 klass->instance_size = MAX (klass->instance_size, real_size);
12599 mono_class_layout_fields (klass);
12603 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12605 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12606 MonoReflectionPropertyBuilder *pb;
12607 MonoImage *image = klass->image;
12608 MonoProperty *properties;
12611 mono_error_init (error);
12614 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12616 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12617 klass->ext->property.first = 0;
12619 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12620 klass->ext->properties = properties;
12621 for (i = 0; i < klass->ext->property.count; ++i) {
12622 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12623 properties [i].parent = klass;
12624 properties [i].attrs = pb->attrs;
12625 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12626 if (!mono_error_ok (error))
12628 if (pb->get_method)
12629 properties [i].get = pb->get_method->mhandle;
12630 if (pb->set_method)
12631 properties [i].set = pb->set_method->mhandle;
12633 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12634 if (pb->def_value) {
12636 const char *p, *p2;
12637 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12638 if (!klass->ext->prop_def_values)
12639 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12640 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12641 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12642 /* Copy the data from the blob since it might get realloc-ed */
12643 p = assembly->blob.data + idx;
12644 len = mono_metadata_decode_blob_size (p, &p2);
12646 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12647 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12652 MonoReflectionEvent *
12653 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12656 MonoEvent *event = g_new0 (MonoEvent, 1);
12659 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12660 mono_error_raise_exception (&error); /* FIXME don't raise here */
12661 klass = mono_class_from_mono_type (type);
12663 event->parent = klass;
12664 event->attrs = eb->attrs;
12665 event->name = mono_string_to_utf8 (eb->name);
12666 if (eb->add_method)
12667 event->add = eb->add_method->mhandle;
12668 if (eb->remove_method)
12669 event->remove = eb->remove_method->mhandle;
12670 if (eb->raise_method)
12671 event->raise = eb->raise_method->mhandle;
12673 #ifndef MONO_SMALL_CONFIG
12674 if (eb->other_methods) {
12676 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12677 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12678 MonoReflectionMethodBuilder *mb =
12679 mono_array_get (eb->other_methods,
12680 MonoReflectionMethodBuilder*, j);
12681 event->other [j] = mb->mhandle;
12686 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12687 mono_error_raise_exception (&error); /* FIXME don't raise here */
12692 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12694 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12695 MonoReflectionEventBuilder *eb;
12696 MonoImage *image = klass->image;
12700 mono_error_init (error);
12703 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12705 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12706 klass->ext->event.first = 0;
12708 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12709 klass->ext->events = events;
12710 for (i = 0; i < klass->ext->event.count; ++i) {
12711 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12712 events [i].parent = klass;
12713 events [i].attrs = eb->attrs;
12714 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12715 if (!mono_error_ok (error))
12717 if (eb->add_method)
12718 events [i].add = eb->add_method->mhandle;
12719 if (eb->remove_method)
12720 events [i].remove = eb->remove_method->mhandle;
12721 if (eb->raise_method)
12722 events [i].raise = eb->raise_method->mhandle;
12724 #ifndef MONO_SMALL_CONFIG
12725 if (eb->other_methods) {
12727 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12728 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12729 MonoReflectionMethodBuilder *mb =
12730 mono_array_get (eb->other_methods,
12731 MonoReflectionMethodBuilder*, j);
12732 events [i].other [j] = mb->mhandle;
12736 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12741 remove_instantiations_of_and_ensure_contents (gpointer key,
12743 gpointer user_data)
12745 MonoType *type = (MonoType*)key;
12746 MonoClass *klass = (MonoClass*)user_data;
12748 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12749 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12756 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12758 mono_error_init (error);
12764 for (i = 0; i < mono_array_length (arr); ++i) {
12765 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12766 if (!mono_error_ok (error))
12771 MonoReflectionType*
12772 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12776 MonoDomain* domain;
12777 MonoReflectionType* res;
12780 domain = mono_object_domain (tb);
12781 klass = mono_class_from_mono_type (tb->type.type);
12784 * Check for user defined Type subclasses.
12786 RESOLVE_TYPE (tb->parent, &error);
12787 mono_error_raise_exception (&error); /* FIXME don't raise here */
12788 check_array_for_usertypes (tb->interfaces, &error);
12789 mono_error_raise_exception (&error); /*FIXME don't raise here */
12791 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12792 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12794 RESOLVE_TYPE (fb->type, &error);
12795 mono_error_raise_exception (&error); /* FIXME don't raise here */
12796 check_array_for_usertypes (fb->modreq, &error);
12797 mono_error_raise_exception (&error); /*FIXME don't raise here */
12798 check_array_for_usertypes (fb->modopt, &error);
12799 mono_error_raise_exception (&error); /*FIXME don't raise here */
12800 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12801 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12802 mono_error_raise_exception (&error); /* FIXME don't raise here */
12808 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12809 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12811 RESOLVE_TYPE (mb->rtype, &error);
12812 mono_error_raise_exception (&error); /* FIXME don't raise here */
12813 check_array_for_usertypes (mb->return_modreq, &error);
12814 mono_error_raise_exception (&error); /*FIXME don't raise here */
12815 check_array_for_usertypes (mb->return_modopt, &error);
12816 mono_error_raise_exception (&error); /*FIXME don't raise here */
12817 check_array_for_usertypes (mb->parameters, &error);
12818 mono_error_raise_exception (&error); /*FIXME don't raise here */
12819 if (mb->param_modreq)
12820 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12821 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12822 mono_error_raise_exception (&error); /*FIXME don't raise here */
12824 if (mb->param_modopt)
12825 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12826 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12827 mono_error_raise_exception (&error); /*FIXME don't raise here */
12833 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12834 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12836 check_array_for_usertypes (mb->parameters, &error);
12837 mono_error_raise_exception (&error); /*FIXME don't raise here */
12838 if (mb->param_modreq)
12839 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12840 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12841 mono_error_raise_exception (&error); /*FIXME don't raise here */
12843 if (mb->param_modopt)
12844 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12845 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12846 mono_error_raise_exception (&error); /*FIXME don't raise here */
12852 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12855 * we need to lock the domain because the lock will be taken inside
12856 * So, we need to keep the locking order correct.
12858 mono_loader_lock ();
12859 mono_domain_lock (domain);
12860 if (klass->wastypebuilder) {
12861 mono_domain_unlock (domain);
12862 mono_loader_unlock ();
12864 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12865 mono_error_raise_exception (&error); /* FIXME don't raise here */
12870 * Fields to set in klass:
12871 * the various flags: delegate/unicode/contextbound etc.
12873 klass->flags = tb->attrs;
12874 klass->has_cctor = 1;
12875 klass->has_finalize = 1;
12876 klass->has_finalize_inited = 1;
12878 mono_class_setup_parent (klass, klass->parent);
12879 /* fool mono_class_setup_supertypes */
12880 klass->supertypes = NULL;
12881 mono_class_setup_supertypes (klass);
12882 mono_class_setup_mono_type (klass);
12885 if (!((MonoDynamicImage*)klass->image)->run) {
12886 if (klass->generic_container) {
12887 /* FIXME: The code below can't handle generic classes */
12888 klass->wastypebuilder = TRUE;
12889 mono_loader_unlock ();
12890 mono_domain_unlock (domain);
12892 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12893 mono_error_raise_exception (&error); /* FIXME don't raise here */
12900 /* enums are done right away */
12901 if (!klass->enumtype)
12902 if (!ensure_runtime_vtable (klass, &error))
12905 if (tb->subtypes) {
12906 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12907 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12908 mono_class_alloc_ext (klass);
12909 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12910 if (!is_ok (&error)) goto failure;
12911 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12915 klass->nested_classes_inited = TRUE;
12917 /* fields and object layout */
12918 if (klass->parent) {
12919 if (!klass->parent->size_inited)
12920 mono_class_init (klass->parent);
12921 klass->instance_size = klass->parent->instance_size;
12922 klass->sizes.class_size = 0;
12923 klass->min_align = klass->parent->min_align;
12924 /* if the type has no fields we won't call the field_setup
12925 * routine which sets up klass->has_references.
12927 klass->has_references |= klass->parent->has_references;
12929 klass->instance_size = sizeof (MonoObject);
12930 klass->min_align = 1;
12933 /* FIXME: handle packing_size and instance_size */
12934 typebuilder_setup_fields (klass, &error);
12935 if (!mono_error_ok (&error))
12937 typebuilder_setup_properties (klass, &error);
12938 if (!mono_error_ok (&error))
12941 typebuilder_setup_events (klass, &error);
12942 if (!mono_error_ok (&error))
12945 klass->wastypebuilder = TRUE;
12948 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12949 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12950 * we want to return normal System.MonoType objects, so clear these out from the cache.
12952 * Together with this we must ensure the contents of all instances to match the created type.
12954 if (domain->type_hash && klass->generic_container)
12955 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12957 mono_domain_unlock (domain);
12958 mono_loader_unlock ();
12960 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12961 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12962 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12965 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12966 mono_error_raise_exception (&error); /* FIXME don't raise here */
12968 g_assert (res != (MonoReflectionType*)tb);
12973 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12974 klass->wastypebuilder = TRUE;
12975 mono_domain_unlock (domain);
12976 mono_loader_unlock ();
12977 mono_error_raise_exception (&error);
12982 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12984 MonoGenericParamFull *param;
12989 image = &gparam->tbuilder->module->dynamic_image->image;
12991 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12993 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12994 g_assert (mono_error_ok (&error));
12995 param->param.num = gparam->index;
12997 if (gparam->mbuilder) {
12998 if (!gparam->mbuilder->generic_container) {
12999 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
13000 mono_error_raise_exception (&error); /* FIXME don't raise here */
13002 MonoClass *klass = mono_class_from_mono_type (tb);
13003 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13004 gparam->mbuilder->generic_container->is_method = TRUE;
13006 * Cannot set owner.method, since the MonoMethod is not created yet.
13007 * Set the image field instead, so type_in_image () works.
13009 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13010 gparam->mbuilder->generic_container->owner.image = klass->image;
13012 param->param.owner = gparam->mbuilder->generic_container;
13013 } else if (gparam->tbuilder) {
13014 if (!gparam->tbuilder->generic_container) {
13015 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
13016 mono_error_raise_exception (&error); /* FIXME don't raise here */
13017 MonoClass *klass = mono_class_from_mono_type (tb);
13018 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13019 gparam->tbuilder->generic_container->owner.klass = klass;
13021 param->param.owner = gparam->tbuilder->generic_container;
13024 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13026 gparam->type.type = &pklass->byval_arg;
13028 mono_class_set_ref_info (pklass, gparam);
13029 mono_image_append_class_to_reflection_info_set (pklass);
13033 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13036 MonoReflectionModuleBuilder *module = sig->module;
13037 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13038 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13043 check_array_for_usertypes (sig->arguments, &error);
13044 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13046 sigbuffer_init (&buf, 32);
13048 sigbuffer_add_value (&buf, 0x07);
13049 sigbuffer_add_value (&buf, na);
13050 if (assembly != NULL){
13051 for (i = 0; i < na; ++i) {
13052 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13053 encode_reflection_type (assembly, type, &buf, &error);
13054 if (!is_ok (&error)) goto fail;
13058 buflen = buf.p - buf.buf;
13059 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13060 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13061 sigbuffer_free (&buf);
13064 sigbuffer_free (&buf);
13065 mono_error_raise_exception (&error); /* FIXME don't raise here */
13070 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13073 MonoDynamicImage *assembly = sig->module->dynamic_image;
13074 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13079 check_array_for_usertypes (sig->arguments, &error);
13080 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13082 sigbuffer_init (&buf, 32);
13084 sigbuffer_add_value (&buf, 0x06);
13085 for (i = 0; i < na; ++i) {
13086 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13087 encode_reflection_type (assembly, type, &buf, &error);
13088 if (!is_ok (&error))
13092 buflen = buf.p - buf.buf;
13093 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13094 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13095 sigbuffer_free (&buf);
13099 sigbuffer_free (&buf);
13100 mono_error_raise_exception (&error); /* FIXME don't raise here */
13105 MonoMethod *handle;
13106 MonoDomain *domain;
13107 } DynamicMethodReleaseData;
13110 * The runtime automatically clean up those after finalization.
13112 static MonoReferenceQueue *dynamic_method_queue;
13115 free_dynamic_method (void *dynamic_method)
13117 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13118 MonoDomain *domain = data->domain;
13119 MonoMethod *method = data->handle;
13122 mono_domain_lock (domain);
13123 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13124 g_hash_table_remove (domain->method_to_dyn_method, method);
13125 mono_domain_unlock (domain);
13126 g_assert (dis_link);
13127 mono_gchandle_free (dis_link);
13129 mono_runtime_free_method (domain, method);
13134 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13137 MonoReferenceQueue *queue;
13138 MonoMethod *handle;
13139 DynamicMethodReleaseData *release_data;
13140 ReflectionMethodBuilder rmb;
13141 MonoMethodSignature *sig;
13143 MonoDomain *domain;
13147 if (mono_runtime_is_shutting_down ())
13148 mono_raise_exception (mono_get_exception_invalid_operation (""));
13150 if (!(queue = dynamic_method_queue)) {
13151 mono_loader_lock ();
13152 if (!(queue = dynamic_method_queue))
13153 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13154 mono_loader_unlock ();
13157 sig = dynamic_method_to_signature (mb);
13159 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13162 * Resolve references.
13165 * Every second entry in the refs array is reserved for storing handle_class,
13166 * which is needed by the ldtoken implementation in the JIT.
13168 rmb.nrefs = mb->nrefs;
13169 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13170 for (i = 0; i < mb->nrefs; i += 2) {
13171 MonoClass *handle_class;
13173 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13175 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13176 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13178 * The referenced DynamicMethod should already be created by the managed
13179 * code, except in the case of circular references. In that case, we store
13180 * method in the refs array, and fix it up later when the referenced
13181 * DynamicMethod is created.
13183 if (method->mhandle) {
13184 ref = method->mhandle;
13186 /* FIXME: GC object stored in unmanaged memory */
13189 /* FIXME: GC object stored in unmanaged memory */
13190 method->referenced_by = g_slist_append (method->referenced_by, mb);
13192 handle_class = mono_defaults.methodhandle_class;
13194 MonoException *ex = NULL;
13195 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13197 ex = mono_get_exception_type_load (NULL, NULL);
13198 else if (mono_security_core_clr_enabled ())
13199 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13203 mono_raise_exception (ex);
13208 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13209 rmb.refs [i + 1] = handle_class;
13213 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13214 if (!is_ok (&error)) {
13216 mono_error_raise_exception (&error); /* FIXME don't raise here */
13218 klass = mono_class_from_mono_type (owner_type);
13220 klass = mono_defaults.object_class;
13223 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13224 release_data = g_new (DynamicMethodReleaseData, 1);
13225 release_data->handle = handle;
13226 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13227 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13228 g_free (release_data);
13230 /* Fix up refs entries pointing at us */
13231 for (l = mb->referenced_by; l; l = l->next) {
13232 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13233 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13236 g_assert (method->mhandle);
13238 data = (gpointer*)wrapper->method_data;
13239 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13240 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13241 data [i + 1] = mb->mhandle;
13244 g_slist_free (mb->referenced_by);
13248 /* ilgen is no longer needed */
13251 domain = mono_domain_get ();
13252 mono_domain_lock (domain);
13253 if (!domain->method_to_dyn_method)
13254 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13255 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13256 mono_domain_unlock (domain);
13259 #endif /* DISABLE_REFLECTION_EMIT */
13263 * mono_reflection_is_valid_dynamic_token:
13265 * Returns TRUE if token is valid.
13269 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13271 return lookup_dyn_token (image, token) != NULL;
13274 MonoMethodSignature *
13275 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13277 MonoMethodSignature *sig;
13278 g_assert (image_is_dynamic (image));
13280 mono_error_init (error);
13282 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13286 return mono_method_signature_checked (method, error);
13289 #ifndef DISABLE_REFLECTION_EMIT
13292 * mono_reflection_lookup_dynamic_token:
13294 * Finish the Builder object pointed to by TOKEN and return the corresponding
13295 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13296 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13299 * LOCKING: Take the loader lock
13302 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13304 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13308 obj = lookup_dyn_token (assembly, token);
13311 g_error ("Could not find required dynamic token 0x%08x", token);
13317 handle_class = &klass;
13318 return resolve_object (image, obj, handle_class, context);
13322 * ensure_complete_type:
13324 * Ensure that KLASS is completed if it is a dynamic type, or references
13328 ensure_complete_type (MonoClass *klass)
13332 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13333 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13335 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13336 mono_error_raise_exception (&error); /* FIXME don't raise here */
13338 // Asserting here could break a lot of code
13339 //g_assert (klass->wastypebuilder);
13342 if (klass->generic_class) {
13343 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13346 for (i = 0; i < inst->type_argc; ++i) {
13347 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13353 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13356 gpointer result = NULL;
13358 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13359 result = mono_string_intern_checked ((MonoString*)obj, &error);
13360 mono_error_raise_exception (&error); /* FIXME don't raise here */
13361 *handle_class = mono_defaults.string_class;
13363 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13364 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13365 mono_error_raise_exception (&error); /* FIXME don't raise here */
13366 MonoClass *mc = mono_class_from_mono_type (type);
13367 if (!mono_class_init (mc))
13368 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13371 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13372 mono_error_raise_exception (&error); /* FIXME don't raise here */
13374 result = mono_class_from_mono_type (inflated);
13375 mono_metadata_free_type (inflated);
13377 result = mono_class_from_mono_type (type);
13379 *handle_class = mono_defaults.typehandle_class;
13381 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13382 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13383 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13384 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13385 result = ((MonoReflectionMethod*)obj)->method;
13388 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13389 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13391 *handle_class = mono_defaults.methodhandle_class;
13393 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13394 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13395 result = mb->mhandle;
13397 /* Type is not yet created */
13398 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13400 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13401 mono_error_raise_exception (&error); /* FIXME don't raise here */
13404 * Hopefully this has been filled in by calling CreateType() on the
13408 * TODO: This won't work if the application finishes another
13409 * TypeBuilder instance instead of this one.
13411 result = mb->mhandle;
13415 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13416 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13418 *handle_class = mono_defaults.methodhandle_class;
13419 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13420 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13422 result = cb->mhandle;
13424 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13426 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13427 mono_error_raise_exception (&error); /* FIXME don't raise here */
13428 result = cb->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, "MonoField") == 0) {
13437 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13439 ensure_complete_type (field->parent);
13441 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13442 mono_error_raise_exception (&error); /* FIXME don't raise here */
13444 MonoClass *klass = mono_class_from_mono_type (inflated);
13445 MonoClassField *inflated_field;
13446 gpointer iter = NULL;
13447 mono_metadata_free_type (inflated);
13448 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13449 if (!strcmp (field->name, inflated_field->name))
13452 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13453 result = inflated_field;
13457 *handle_class = mono_defaults.fieldhandle_class;
13459 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13460 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13461 result = fb->handle;
13464 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13466 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13467 mono_error_raise_exception (&error); /* FIXME don't raise here */
13468 result = fb->handle;
13471 if (fb->handle && fb->handle->parent->generic_container) {
13472 MonoClass *klass = fb->handle->parent;
13473 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13474 mono_error_raise_exception (&error); /* FIXME don't raise here */
13476 MonoClass *inflated = mono_class_from_mono_type (type);
13478 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13480 mono_metadata_free_type (type);
13482 *handle_class = mono_defaults.fieldhandle_class;
13483 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13484 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13485 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13486 mono_error_raise_exception (&error); /* FIXME don't raise here */
13489 klass = type->data.klass;
13490 if (klass->wastypebuilder) {
13491 /* Already created */
13495 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13496 mono_error_raise_exception (&error); /* FIXME don't raise here */
13497 result = type->data.klass;
13500 *handle_class = mono_defaults.typehandle_class;
13501 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13502 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13503 MonoMethodSignature *sig;
13506 if (helper->arguments)
13507 nargs = mono_array_length (helper->arguments);
13511 sig = mono_metadata_signature_alloc (image, nargs);
13512 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13513 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13515 if (helper->unmanaged_call_conv) { /* unmanaged */
13516 sig->call_convention = helper->unmanaged_call_conv - 1;
13517 sig->pinvoke = TRUE;
13518 } else if (helper->call_conv & 0x02) {
13519 sig->call_convention = MONO_CALL_VARARG;
13521 sig->call_convention = MONO_CALL_DEFAULT;
13524 sig->param_count = nargs;
13525 /* TODO: Copy type ? */
13526 sig->ret = helper->return_type->type;
13527 for (i = 0; i < nargs; ++i) {
13528 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13529 mono_error_raise_exception (&error); /* FIXME don't raise here */
13533 *handle_class = NULL;
13534 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13535 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13536 /* Already created by the managed code */
13537 g_assert (method->mhandle);
13538 result = method->mhandle;
13539 *handle_class = mono_defaults.methodhandle_class;
13540 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13541 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13542 mono_error_raise_exception (&error); /* FIXME don't raise here */
13543 type = mono_class_inflate_generic_type_checked (type, context, &error);
13544 mono_error_raise_exception (&error); /* FIXME don't raise here */
13546 result = mono_class_from_mono_type (type);
13547 *handle_class = mono_defaults.typehandle_class;
13549 mono_metadata_free_type (type);
13550 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13551 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13552 mono_error_raise_exception (&error); /* FIXME don't raise here */
13553 type = mono_class_inflate_generic_type_checked (type, context, &error);
13554 mono_error_raise_exception (&error); /* FIXME don't raise here */
13556 result = mono_class_from_mono_type (type);
13557 *handle_class = mono_defaults.typehandle_class;
13559 mono_metadata_free_type (type);
13560 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13561 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13562 MonoClass *inflated;
13564 MonoClassField *field;
13566 if (is_sre_field_builder (mono_object_class (f->fb)))
13567 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13568 else if (is_sr_mono_field (mono_object_class (f->fb)))
13569 field = ((MonoReflectionField*)f->fb)->field;
13571 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)));
13573 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13574 mono_error_raise_exception (&error); /* FIXME don't raise here */
13575 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13576 mono_error_raise_exception (&error); /* FIXME don't raise here */
13578 inflated = mono_class_from_mono_type (type);
13580 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13581 ensure_complete_type (field->parent);
13583 mono_metadata_free_type (type);
13584 *handle_class = mono_defaults.fieldhandle_class;
13585 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13586 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13587 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13588 mono_error_raise_exception (&error); /* FIXME don't raise here */
13589 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13590 mono_error_raise_exception (&error); /* FIXME don't raise here */
13592 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13593 MonoMethod *method;
13595 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13596 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13597 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13598 method = ((MonoReflectionMethod *)c->cb)->method;
13600 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)));
13602 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13603 *handle_class = mono_defaults.methodhandle_class;
13604 mono_metadata_free_type (type);
13605 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13606 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13607 if (m->method_args) {
13608 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13609 mono_error_raise_exception (&error); /* FIXME don't raise here */
13611 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13612 mono_error_assert_ok (&error);
13615 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13616 mono_error_raise_exception (&error); /* FIXME don't raise here */
13617 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13618 mono_error_raise_exception (&error); /* FIXME don't raise here */
13620 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13621 MonoMethod *method;
13623 if (is_sre_method_builder (mono_object_class (m->mb)))
13624 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13625 else if (is_sr_mono_method (mono_object_class (m->mb)))
13626 method = ((MonoReflectionMethod *)m->mb)->method;
13628 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)));
13630 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13631 mono_metadata_free_type (type);
13633 *handle_class = mono_defaults.methodhandle_class;
13634 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13635 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13638 MonoMethod *method;
13642 mtype = mono_reflection_type_get_handle (m->parent, &error);
13643 mono_error_raise_exception (&error); /* FIXME don't raise here */
13644 klass = mono_class_from_mono_type (mtype);
13646 /* Find the method */
13648 name = mono_string_to_utf8 (m->name);
13650 while ((method = mono_class_get_methods (klass, &iter))) {
13651 if (!strcmp (method->name, name))
13658 // FIXME: Check parameters/return value etc. match
13661 *handle_class = mono_defaults.methodhandle_class;
13662 } else if (is_sre_array (mono_object_get_class(obj)) ||
13663 is_sre_byref (mono_object_get_class(obj)) ||
13664 is_sre_pointer (mono_object_get_class(obj))) {
13665 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13666 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13667 mono_error_raise_exception (&error); /* FIXME don't raise here */
13670 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13671 mono_error_raise_exception (&error); /* FIXME don't raise here */
13673 result = mono_class_from_mono_type (inflated);
13674 mono_metadata_free_type (inflated);
13676 result = mono_class_from_mono_type (type);
13678 *handle_class = mono_defaults.typehandle_class;
13680 g_print ("%s\n", obj->vtable->klass->name);
13681 g_assert_not_reached ();
13686 #else /* DISABLE_REFLECTION_EMIT */
13689 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13691 g_assert_not_reached ();
13696 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13698 g_assert_not_reached ();
13702 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13704 g_assert_not_reached ();
13708 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13710 g_assert_not_reached ();
13714 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13716 g_assert_not_reached ();
13720 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13722 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13726 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13728 g_assert_not_reached ();
13732 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13734 g_assert_not_reached ();
13737 MonoReflectionModule *
13738 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13740 g_assert_not_reached ();
13745 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13747 g_assert_not_reached ();
13752 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13754 g_assert_not_reached ();
13759 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13760 gboolean create_open_instance, gboolean register_token, MonoError *error)
13762 g_assert_not_reached ();
13767 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13772 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13774 g_assert_not_reached ();
13778 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13781 *num_overrides = 0;
13784 MonoReflectionEvent *
13785 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13787 g_assert_not_reached ();
13791 MonoReflectionType*
13792 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13794 g_assert_not_reached ();
13799 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13801 g_assert_not_reached ();
13805 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13807 g_assert_not_reached ();
13812 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13814 g_assert_not_reached ();
13819 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13824 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13830 mono_reflection_type_get_handle (MonoReflectionType* ref)
13838 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13840 g_assert_not_reached ();
13843 #endif /* DISABLE_REFLECTION_EMIT */
13845 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13846 const static guint32 declsec_flags_map[] = {
13847 0x00000000, /* empty */
13848 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13849 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13850 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13851 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13852 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13853 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13854 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13855 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13856 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13857 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13858 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13859 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13860 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13861 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13862 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13863 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13864 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13865 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13869 * Returns flags that includes all available security action associated to the handle.
13870 * @token: metadata token (either for a class or a method)
13871 * @image: image where resides the metadata.
13874 mono_declsec_get_flags (MonoImage *image, guint32 token)
13876 int index = mono_metadata_declsec_from_index (image, token);
13877 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13878 guint32 result = 0;
13882 /* HasSecurity can be present for other, not specially encoded, attributes,
13883 e.g. SuppressUnmanagedCodeSecurityAttribute */
13887 for (i = index; i < t->rows; i++) {
13888 guint32 cols [MONO_DECL_SECURITY_SIZE];
13890 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13891 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13894 action = cols [MONO_DECL_SECURITY_ACTION];
13895 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13896 result |= declsec_flags_map [action];
13898 g_assert_not_reached ();
13905 * Get the security actions (in the form of flags) associated with the specified method.
13907 * @method: The method for which we want the declarative security flags.
13908 * Return the declarative security flags for the method (only).
13910 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13911 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13914 mono_declsec_flags_from_method (MonoMethod *method)
13916 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13917 /* FIXME: No cache (for the moment) */
13918 guint32 idx = mono_method_get_index (method);
13919 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13920 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13921 return mono_declsec_get_flags (method->klass->image, idx);
13927 * Get the security actions (in the form of flags) associated with the specified class.
13929 * @klass: The class for which we want the declarative security flags.
13930 * Return the declarative security flags for the class.
13932 * Note: We cache the flags inside the MonoClass structure as this will get
13933 * called very often (at least for each method).
13936 mono_declsec_flags_from_class (MonoClass *klass)
13938 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13939 if (!klass->ext || !klass->ext->declsec_flags) {
13942 idx = mono_metadata_token_index (klass->type_token);
13943 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13944 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13945 mono_loader_lock ();
13946 mono_class_alloc_ext (klass);
13947 mono_loader_unlock ();
13948 /* we cache the flags on classes */
13949 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13951 return klass->ext->declsec_flags;
13957 * Get the security actions (in the form of flags) associated with the specified assembly.
13959 * @assembly: The assembly for which we want the declarative security flags.
13960 * Return the declarative security flags for the assembly.
13963 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13965 guint32 idx = 1; /* there is only one assembly */
13966 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13967 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13968 return mono_declsec_get_flags (assembly->image, idx);
13973 * Fill actions for the specific index (which may either be an encoded class token or
13974 * an encoded method token) from the metadata image.
13975 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13978 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13979 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13981 MonoBoolean result = FALSE;
13983 guint32 cols [MONO_DECL_SECURITY_SIZE];
13984 int index = mono_metadata_declsec_from_index (image, token);
13987 t = &image->tables [MONO_TABLE_DECLSECURITY];
13988 for (i = index; i < t->rows; i++) {
13989 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13991 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13994 /* if present only replace (class) permissions with method permissions */
13995 /* if empty accept either class or method permissions */
13996 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13997 if (!actions->demand.blob) {
13998 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13999 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14000 actions->demand.blob = (char*) (blob + 2);
14001 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14004 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14005 if (!actions->noncasdemand.blob) {
14006 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14007 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14008 actions->noncasdemand.blob = (char*) (blob + 2);
14009 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14012 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14013 if (!actions->demandchoice.blob) {
14014 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14015 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14016 actions->demandchoice.blob = (char*) (blob + 2);
14017 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14027 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14028 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14030 guint32 idx = mono_metadata_token_index (klass->type_token);
14031 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14032 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14033 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14037 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14038 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14040 guint32 idx = mono_method_get_index (method);
14041 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14042 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14043 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14047 * Collect all actions (that requires to generate code in mini) assigned for
14048 * the specified method.
14049 * Note: Don't use the content of actions if the function return FALSE.
14052 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14054 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14055 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14056 MonoBoolean result = FALSE;
14059 /* quick exit if no declarative security is present in the metadata */
14060 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14063 /* we want the original as the wrapper is "free" of the security informations */
14064 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14065 method = mono_marshal_method_from_wrapper (method);
14070 /* First we look for method-level attributes */
14071 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14072 mono_class_init (method->klass);
14073 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14075 result = mono_declsec_get_method_demands_params (method, demands,
14076 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14079 /* Here we use (or create) the class declarative cache to look for demands */
14080 flags = mono_declsec_flags_from_class (method->klass);
14081 if (flags & mask) {
14083 mono_class_init (method->klass);
14084 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14086 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14087 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14090 /* The boolean return value is used as a shortcut in case nothing needs to
14091 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14097 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14099 * Note: Don't use the content of actions if the function return FALSE.
14102 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14104 MonoBoolean result = FALSE;
14107 /* quick exit if no declarative security is present in the metadata */
14108 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14111 /* we want the original as the wrapper is "free" of the security informations */
14112 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14113 method = mono_marshal_method_from_wrapper (method);
14118 /* results are independant - zeroize both */
14119 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14120 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14122 /* First we look for method-level attributes */
14123 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14124 mono_class_init (method->klass);
14126 result = mono_declsec_get_method_demands_params (method, cmethod,
14127 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14130 /* Here we use (or create) the class declarative cache to look for demands */
14131 flags = mono_declsec_flags_from_class (method->klass);
14132 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14133 mono_class_init (method->klass);
14135 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14136 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14143 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14145 * @klass The inherited class - this is the class that provides the security check (attributes)
14147 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14149 * Note: Don't use the content of actions if the function return FALSE.
14152 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14154 MonoBoolean result = FALSE;
14157 /* quick exit if no declarative security is present in the metadata */
14158 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14161 /* Here we use (or create) the class declarative cache to look for demands */
14162 flags = mono_declsec_flags_from_class (klass);
14163 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14164 mono_class_init (klass);
14165 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14167 result |= mono_declsec_get_class_demands_params (klass, demands,
14168 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14175 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14177 * Note: Don't use the content of actions if the function return FALSE.
14180 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14182 /* quick exit if no declarative security is present in the metadata */
14183 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14186 /* we want the original as the wrapper is "free" of the security informations */
14187 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14188 method = mono_marshal_method_from_wrapper (method);
14193 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14194 mono_class_init (method->klass);
14195 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14197 return mono_declsec_get_method_demands_params (method, demands,
14198 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14205 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14207 guint32 cols [MONO_DECL_SECURITY_SIZE];
14211 int index = mono_metadata_declsec_from_index (image, token);
14215 t = &image->tables [MONO_TABLE_DECLSECURITY];
14216 for (i = index; i < t->rows; i++) {
14217 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14219 /* shortcut - index are ordered */
14220 if (token != cols [MONO_DECL_SECURITY_PARENT])
14223 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14224 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14225 entry->blob = (char*) (metadata + 2);
14226 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14235 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14237 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14238 guint32 idx = mono_method_get_index (method);
14239 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14240 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14241 return get_declsec_action (method->klass->image, idx, action, entry);
14247 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14250 guint32 flags = mono_declsec_flags_from_class (klass);
14251 if (declsec_flags_map [action] & flags) {
14252 guint32 idx = mono_metadata_token_index (klass->type_token);
14253 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14254 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14255 return get_declsec_action (klass->image, idx, action, entry);
14261 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14263 guint32 idx = 1; /* there is only one assembly */
14264 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14265 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14267 return get_declsec_action (assembly->image, idx, action, entry);
14271 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14274 MonoObject *res, *exc;
14276 static MonoMethod *method = NULL;
14278 if (method == NULL) {
14279 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14284 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14285 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14287 g_assert (mono_class_get_ref_info (klass));
14288 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14290 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14291 mono_error_raise_exception (&error); /* FIXME don't raise here */
14293 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14295 if (exc || !mono_error_ok (&error)) {
14296 mono_error_cleanup (&error);
14299 return *(MonoBoolean*)mono_object_unbox (res);
14303 * mono_reflection_type_get_type:
14304 * @reftype: the System.Type object
14306 * Returns the MonoType* associated with the C# System.Type object @reftype.
14309 mono_reflection_type_get_type (MonoReflectionType *reftype)
14311 g_assert (reftype);
14314 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14315 mono_error_assert_ok (&error);
14320 * mono_reflection_assembly_get_assembly:
14321 * @refassembly: the System.Reflection.Assembly object
14323 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14326 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14328 g_assert (refassembly);
14330 return refassembly->assembly;