2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, 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)
3602 int i, count, len, pos;
3607 count += mono_array_length (modreq);
3609 count += mono_array_length (modopt);
3612 return mono_metadata_type_dup (NULL, type);
3614 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3615 t = (MonoType *)g_malloc (len);
3616 memcpy (t, type, MONO_SIZEOF_TYPE);
3618 t->num_mods = count;
3621 for (i = 0; i < mono_array_length (modreq); ++i) {
3622 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3623 mono_error_raise_exception (&error); /* FIXME don't raise here */
3624 t->modifiers [pos].required = 1;
3625 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3630 for (i = 0; i < mono_array_length (modopt); ++i) {
3631 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3632 mono_error_raise_exception (&error); /* FIXME don't raise here */
3633 t->modifiers [pos].required = 0;
3634 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3643 init_type_builder_generics (MonoObject *type)
3645 MonoReflectionTypeBuilder *tb;
3647 if (!is_sre_type_builder(mono_object_class (type)))
3649 tb = (MonoReflectionTypeBuilder *)type;
3651 if (tb && tb->generic_container)
3652 mono_reflection_create_generic_class (tb);
3656 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3659 MonoDynamicTable *table;
3660 MonoType *custom = NULL, *type;
3662 guint32 token, pclass, parent, sig;
3665 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3669 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3670 mono_error_raise_exception (&error); /* FIXME don't raise here */
3671 /* FIXME: is this call necessary? */
3672 mono_class_from_mono_type (typeb);
3673 name = mono_string_to_utf8 (fb->name);
3675 /*FIXME this is one more layer of ugliness due how types are created.*/
3676 init_type_builder_generics (fb->type);
3678 /* fb->type does not include the custom modifiers */
3679 /* FIXME: We should do this in one place when a fieldbuilder is created */
3680 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3681 mono_error_raise_exception (&error); /* FIXME don't raise here */
3683 if (fb->modreq || fb->modopt)
3684 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3686 sig = fieldref_encode_signature (assembly, NULL, type);
3689 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, &error);
3690 mono_error_raise_exception (&error); /* FIXME don't raise here */
3691 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3693 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3694 parent >>= MONO_TYPEDEFORREF_BITS;
3696 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3698 if (assembly->save) {
3699 alloc_table (table, table->rows + 1);
3700 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3701 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3702 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3703 values [MONO_MEMBERREF_SIGNATURE] = sig;
3706 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3708 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3714 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3721 if (!assembly->save)
3724 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3725 g_assert (helper->type == 2);
3727 if (helper->arguments)
3728 nargs = mono_array_length (helper->arguments);
3732 sigbuffer_init (&buf, 32);
3734 /* Encode calling convention */
3735 /* Change Any to Standard */
3736 if ((helper->call_conv & 0x03) == 0x03)
3737 helper->call_conv = 0x01;
3738 /* explicit_this implies has_this */
3739 if (helper->call_conv & 0x40)
3740 helper->call_conv &= 0x20;
3742 if (helper->call_conv == 0) { /* Unmanaged */
3743 idx = helper->unmanaged_call_conv - 1;
3746 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3747 if (helper->call_conv & 0x02) /* varargs */
3751 sigbuffer_add_byte (&buf, idx);
3752 sigbuffer_add_value (&buf, nargs);
3753 encode_reflection_type (assembly, helper->return_type, &buf, &error);
3754 if (!is_ok (&error))
3756 for (i = 0; i < nargs; ++i) {
3757 MonoArray *modreqs = NULL;
3758 MonoArray *modopts = NULL;
3759 MonoReflectionType *pt;
3761 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3762 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3763 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3764 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3766 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3767 if (!is_ok (&error))
3769 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3770 encode_reflection_type (assembly, pt, &buf, &error);
3771 if (!is_ok (&error))
3774 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3775 sigbuffer_free (&buf);
3779 sigbuffer_free (&buf);
3780 mono_error_raise_exception (&error); /* FIXME don't raise here */
3781 g_assert_not_reached ();
3785 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3788 MonoDynamicTable *table;
3791 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3792 idx = table->next_idx ++;
3794 alloc_table (table, table->rows);
3795 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3797 values [MONO_STAND_ALONE_SIGNATURE] =
3798 mono_reflection_encode_sighelper (assembly, helper);
3804 reflection_cc_to_file (int call_conv) {
3805 switch (call_conv & 0x3) {
3807 case 1: return MONO_CALL_DEFAULT;
3808 case 2: return MONO_CALL_VARARG;
3810 g_assert_not_reached ();
3814 #endif /* !DISABLE_REFLECTION_EMIT */
3818 MonoMethodSignature *sig;
3823 #ifndef DISABLE_REFLECTION_EMIT
3825 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3831 MonoMethodSignature *sig;
3835 name = mono_string_to_utf8 (m->name);
3836 nparams = mono_array_length (m->parameters);
3837 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3839 sig->sentinelpos = -1;
3840 sig->call_convention = reflection_cc_to_file (m->call_conv);
3841 sig->param_count = nparams;
3843 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3844 mono_error_raise_exception (&error); /* FIXME don't raise here */
3846 sig->ret = &mono_defaults.void_class->byval_arg;
3848 mtype = mono_reflection_type_get_handle (m->parent, &error);
3849 mono_error_raise_exception (&error); /* FIXME don't raise here */
3851 for (i = 0; i < nparams; ++i) {
3852 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3853 mono_error_raise_exception (&error); /* FIXME don't raise here */
3856 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3857 am = (ArrayMethod *)tmp->data;
3858 if (strcmp (name, am->name) == 0 &&
3859 mono_metadata_type_equal (am->parent, mtype) &&
3860 mono_metadata_signature_equal (am->sig, sig)) {
3863 m->table_idx = am->token & 0xffffff;
3867 am = g_new0 (ArrayMethod, 1);
3871 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3872 method_encode_signature (assembly, sig));
3873 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3874 m->table_idx = am->token & 0xffffff;
3879 * Insert into the metadata tables all the info about the TypeBuilder tb.
3880 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3883 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3885 MonoDynamicTable *table;
3887 int i, is_object = 0, is_system = 0;
3890 mono_error_init (error);
3892 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3893 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3894 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3895 n = mono_string_to_utf8 (tb->name);
3896 if (strcmp (n, "Object") == 0)
3898 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3900 n = mono_string_to_utf8 (tb->nspace);
3901 if (strcmp (n, "System") == 0)
3903 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3905 if (tb->parent && !(is_system && is_object) &&
3906 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3907 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3908 return_val_if_nok (error, FALSE);
3909 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3911 values [MONO_TYPEDEF_EXTENDS] = 0;
3913 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3914 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3917 * if we have explicitlayout or sequentiallayouts, output data in the
3918 * ClassLayout table.
3920 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3921 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3922 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3924 alloc_table (table, table->rows);
3925 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3926 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3927 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3928 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3931 /* handle interfaces */
3932 if (tb->interfaces) {
3933 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3935 table->rows += mono_array_length (tb->interfaces);
3936 alloc_table (table, table->rows);
3937 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3938 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3939 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3940 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3941 return_val_if_nok (error, FALSE);
3942 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3943 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3944 values += MONO_INTERFACEIMPL_SIZE;
3950 table = &assembly->tables [MONO_TABLE_FIELD];
3951 table->rows += tb->num_fields;
3952 alloc_table (table, table->rows);
3953 for (i = 0; i < tb->num_fields; ++i) {
3954 mono_image_get_field_info (
3955 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3956 return_val_if_nok (error, FALSE);
3960 /* handle constructors */
3962 table = &assembly->tables [MONO_TABLE_METHOD];
3963 table->rows += mono_array_length (tb->ctors);
3964 alloc_table (table, table->rows);
3965 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3966 if (!mono_image_get_ctor_info (domain,
3967 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3973 /* handle methods */
3975 table = &assembly->tables [MONO_TABLE_METHOD];
3976 table->rows += tb->num_methods;
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < tb->num_methods; ++i) {
3979 if (!mono_image_get_method_info (
3980 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3985 /* Do the same with properties etc.. */
3986 if (tb->events && mono_array_length (tb->events)) {
3987 table = &assembly->tables [MONO_TABLE_EVENT];
3988 table->rows += mono_array_length (tb->events);
3989 alloc_table (table, table->rows);
3990 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3992 alloc_table (table, table->rows);
3993 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3994 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3995 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3996 for (i = 0; i < mono_array_length (tb->events); ++i) {
3997 mono_image_get_event_info (
3998 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
3999 return_val_if_nok (error, FALSE);
4002 if (tb->properties && mono_array_length (tb->properties)) {
4003 table = &assembly->tables [MONO_TABLE_PROPERTY];
4004 table->rows += mono_array_length (tb->properties);
4005 alloc_table (table, table->rows);
4006 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4008 alloc_table (table, table->rows);
4009 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4010 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4011 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4012 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4013 mono_image_get_property_info (
4014 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4015 return_val_if_nok (error, FALSE);
4019 /* handle generic parameters */
4020 if (tb->generic_params) {
4021 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4022 table->rows += mono_array_length (tb->generic_params);
4023 alloc_table (table, table->rows);
4024 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4025 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4027 mono_image_get_generic_param_info (
4028 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4032 mono_image_add_decl_security (assembly,
4033 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4036 MonoDynamicTable *ntable;
4038 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4039 ntable->rows += mono_array_length (tb->subtypes);
4040 alloc_table (ntable, ntable->rows);
4041 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4043 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4044 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4046 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4047 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4048 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4049 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4050 mono_string_to_utf8 (tb->name), tb->table_idx,
4051 ntable->next_idx, ntable->rows);*/
4052 values += MONO_NESTED_CLASS_SIZE;
4062 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4066 mono_ptr_array_append (*types, type);
4068 if (!type->subtypes)
4071 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4072 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4073 collect_types (types, subtype);
4078 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4080 if ((*type1)->table_idx < (*type2)->table_idx)
4083 if ((*type1)->table_idx > (*type2)->table_idx)
4090 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4093 mono_error_init (error);
4096 for (i = 0; i < mono_array_length (pinfo); ++i) {
4097 MonoReflectionParamBuilder *pb;
4098 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4101 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4109 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4112 mono_error_init (error);
4114 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4117 for (i = 0; i < tb->num_fields; ++i) {
4118 MonoReflectionFieldBuilder* fb;
4119 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4120 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4125 for (i = 0; i < mono_array_length (tb->events); ++i) {
4126 MonoReflectionEventBuilder* eb;
4127 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4128 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4132 if (tb->properties) {
4133 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4134 MonoReflectionPropertyBuilder* pb;
4135 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4136 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4141 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4142 MonoReflectionCtorBuilder* cb;
4143 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4144 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4145 !params_add_cattrs (assembly, cb->pinfo, error))
4151 for (i = 0; i < tb->num_methods; ++i) {
4152 MonoReflectionMethodBuilder* mb;
4153 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4154 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4155 !params_add_cattrs (assembly, mb->pinfo, error))
4161 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4162 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4171 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4175 mono_error_init (error);
4177 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4180 if (moduleb->global_methods) {
4181 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4182 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4183 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4184 !params_add_cattrs (assembly, mb->pinfo, error))
4189 if (moduleb->global_fields) {
4190 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4191 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4192 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4197 if (moduleb->types) {
4198 for (i = 0; i < moduleb->num_types; ++i) {
4199 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4208 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4210 MonoDynamicTable *table;
4214 char *b = blob_size;
4217 table = &assembly->tables [MONO_TABLE_FILE];
4219 alloc_table (table, table->rows);
4220 values = table->values + table->next_idx * MONO_FILE_SIZE;
4221 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4222 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4223 if (image_is_dynamic (module->image)) {
4224 /* This depends on the fact that the main module is emitted last */
4225 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4226 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4229 path = g_strdup (module->image->name);
4231 mono_sha1_get_digest_from_file (path, hash);
4234 mono_metadata_encode_value (20, b, &b);
4235 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4236 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4241 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4243 MonoDynamicTable *table;
4246 table = &assembly->tables [MONO_TABLE_MODULE];
4247 mb->table_idx = table->next_idx ++;
4248 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4249 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4252 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4253 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4254 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4255 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4259 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4260 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4262 MonoDynamicTable *table;
4266 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4267 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4270 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4272 alloc_table (table, table->rows);
4273 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4275 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4276 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4277 if (klass->nested_in)
4278 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4280 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4281 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4282 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4284 res = table->next_idx;
4288 /* Emit nested types */
4289 if (klass->ext && klass->ext->nested_classes) {
4292 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4293 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4300 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4301 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4307 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4308 mono_error_raise_exception (&error); /* FIXME don't raise here */
4310 klass = mono_class_from_mono_type (t);
4312 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4314 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4315 parent_index, assembly);
4319 * We need to do this ourselves since klass->nested_classes is not set up.
4322 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4323 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4328 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4329 guint32 module_index, MonoDynamicImage *assembly)
4331 MonoImage *image = module->image;
4335 t = &image->tables [MONO_TABLE_TYPEDEF];
4337 for (i = 0; i < t->rows; ++i) {
4339 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4340 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4342 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4343 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4348 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4350 MonoDynamicTable *table;
4352 guint32 scope, scope_idx, impl, current_idx;
4353 gboolean forwarder = TRUE;
4354 gpointer iter = NULL;
4357 if (klass->nested_in) {
4358 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4361 scope = resolution_scope_from_image (assembly, klass->image);
4362 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4363 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4364 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4367 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4370 alloc_table (table, table->rows);
4371 current_idx = table->next_idx;
4372 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4374 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4375 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4376 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4377 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4378 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4382 while ((nested = mono_class_get_nested_types (klass, &iter)))
4383 add_exported_type (assemblyb, assembly, nested, current_idx);
4387 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4393 if (!assemblyb->type_forwarders)
4396 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4397 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4402 type = mono_reflection_type_get_handle (t, &error);
4403 mono_error_assert_ok (&error);
4406 klass = mono_class_from_mono_type (type);
4408 add_exported_type (assemblyb, assembly, klass, 0);
4412 #define align_pointer(base,p)\
4414 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4416 (p) += 4 - (__diff & 3);\
4420 compare_constants (const void *a, const void *b)
4422 const guint32 *a_values = (const guint32 *)a;
4423 const guint32 *b_values = (const guint32 *)b;
4424 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4428 compare_semantics (const void *a, const void *b)
4430 const guint32 *a_values = (const guint32 *)a;
4431 const guint32 *b_values = (const guint32 *)b;
4432 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4435 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4439 compare_custom_attrs (const void *a, const void *b)
4441 const guint32 *a_values = (const guint32 *)a;
4442 const guint32 *b_values = (const guint32 *)b;
4444 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4448 compare_field_marshal (const void *a, const void *b)
4450 const guint32 *a_values = (const guint32 *)a;
4451 const guint32 *b_values = (const guint32 *)b;
4453 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4457 compare_nested (const void *a, const void *b)
4459 const guint32 *a_values = (const guint32 *)a;
4460 const guint32 *b_values = (const guint32 *)b;
4462 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4466 compare_genericparam (const void *a, const void *b)
4469 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4470 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4472 if ((*b_entry)->owner == (*a_entry)->owner) {
4473 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4474 mono_error_assert_ok (&error);
4475 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4476 mono_error_assert_ok (&error);
4478 mono_type_get_generic_param_num (a_type) -
4479 mono_type_get_generic_param_num (b_type);
4481 return (*a_entry)->owner - (*b_entry)->owner;
4485 compare_declsecurity_attrs (const void *a, const void *b)
4487 const guint32 *a_values = (const guint32 *)a;
4488 const guint32 *b_values = (const guint32 *)b;
4490 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4494 compare_interface_impl (const void *a, const void *b)
4496 const guint32 *a_values = (const guint32 *)a;
4497 const guint32 *b_values = (const guint32 *)b;
4499 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4503 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4507 pad_heap (MonoDynamicStream *sh)
4509 if (sh->index & 3) {
4510 int sz = 4 - (sh->index & 3);
4511 memset (sh->data + sh->index, 0, sz);
4518 MonoDynamicStream *stream;
4522 * build_compressed_metadata() fills in the blob of data that represents the
4523 * raw metadata as it will be saved in the PE file. The five streams are output
4524 * and the metadata tables are comnpressed from the guint32 array representation,
4525 * to the compressed on-disk format.
4528 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4530 MonoDynamicTable *table;
4532 guint64 valid_mask = 0;
4533 guint64 sorted_mask;
4534 guint32 heapt_size = 0;
4535 guint32 meta_size = 256; /* allow for header and other stuff */
4536 guint32 table_offset;
4537 guint32 ntables = 0;
4543 struct StreamDesc stream_desc [5];
4545 mono_error_init (error);
4547 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4548 for (i = 0; i < assembly->gen_params->len; i++) {
4549 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4550 if (!write_generic_param_entry (assembly, entry, error))
4554 stream_desc [0].name = "#~";
4555 stream_desc [0].stream = &assembly->tstream;
4556 stream_desc [1].name = "#Strings";
4557 stream_desc [1].stream = &assembly->sheap;
4558 stream_desc [2].name = "#US";
4559 stream_desc [2].stream = &assembly->us;
4560 stream_desc [3].name = "#Blob";
4561 stream_desc [3].stream = &assembly->blob;
4562 stream_desc [4].name = "#GUID";
4563 stream_desc [4].stream = &assembly->guid;
4565 /* tables that are sorted */
4566 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4567 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4568 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4569 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4570 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4571 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4572 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4574 /* Compute table sizes */
4575 /* the MonoImage has already been created in mono_image_basic_init() */
4576 meta = &assembly->image;
4578 /* sizes should be multiple of 4 */
4579 pad_heap (&assembly->blob);
4580 pad_heap (&assembly->guid);
4581 pad_heap (&assembly->sheap);
4582 pad_heap (&assembly->us);
4584 /* Setup the info used by compute_sizes () */
4585 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4586 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4587 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4589 meta_size += assembly->blob.index;
4590 meta_size += assembly->guid.index;
4591 meta_size += assembly->sheap.index;
4592 meta_size += assembly->us.index;
4594 for (i=0; i < MONO_TABLE_NUM; ++i)
4595 meta->tables [i].rows = assembly->tables [i].rows;
4597 for (i = 0; i < MONO_TABLE_NUM; i++){
4598 if (meta->tables [i].rows == 0)
4600 valid_mask |= (guint64)1 << i;
4602 meta->tables [i].row_size = mono_metadata_compute_size (
4603 meta, i, &meta->tables [i].size_bitfield);
4604 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4606 heapt_size += 24; /* #~ header size */
4607 heapt_size += ntables * 4;
4608 /* make multiple of 4 */
4611 meta_size += heapt_size;
4612 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4613 p = (unsigned char*)meta->raw_metadata;
4614 /* the metadata signature */
4615 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4616 /* version numbers and 4 bytes reserved */
4617 int16val = (guint16*)p;
4618 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4619 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4621 /* version string */
4622 int32val = (guint32*)p;
4623 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4625 memcpy (p, meta->version, strlen (meta->version));
4626 p += GUINT32_FROM_LE (*int32val);
4627 align_pointer (meta->raw_metadata, p);
4628 int16val = (guint16*)p;
4629 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4630 *int16val = GUINT16_TO_LE (5); /* number of streams */
4634 * write the stream info.
4636 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4637 table_offset += 3; table_offset &= ~3;
4639 assembly->tstream.index = heapt_size;
4640 for (i = 0; i < 5; ++i) {
4641 int32val = (guint32*)p;
4642 stream_desc [i].stream->offset = table_offset;
4643 *int32val++ = GUINT32_TO_LE (table_offset);
4644 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4645 table_offset += GUINT32_FROM_LE (*int32val);
4646 table_offset += 3; table_offset &= ~3;
4648 strcpy ((char*)p, stream_desc [i].name);
4649 p += strlen (stream_desc [i].name) + 1;
4650 align_pointer (meta->raw_metadata, p);
4653 * now copy the data, the table stream header and contents goes first.
4655 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4656 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4657 int32val = (guint32*)p;
4658 *int32val = GUINT32_TO_LE (0); /* reserved */
4661 *p++ = 2; /* version */
4664 if (meta->idx_string_wide)
4666 if (meta->idx_guid_wide)
4668 if (meta->idx_blob_wide)
4671 *p++ = 1; /* reserved */
4672 int64val = (guint64*)p;
4673 *int64val++ = GUINT64_TO_LE (valid_mask);
4674 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4676 int32val = (guint32*)p;
4677 for (i = 0; i < MONO_TABLE_NUM; i++){
4678 if (meta->tables [i].rows == 0)
4680 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4682 p = (unsigned char*)int32val;
4684 /* sort the tables that still need sorting */
4685 table = &assembly->tables [MONO_TABLE_CONSTANT];
4687 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4688 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4690 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4691 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4693 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4694 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4696 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4697 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4699 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4700 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4701 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4703 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4704 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4706 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4708 /* compress the tables */
4709 for (i = 0; i < MONO_TABLE_NUM; i++){
4712 guint32 bitfield = meta->tables [i].size_bitfield;
4713 if (!meta->tables [i].rows)
4715 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4716 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4717 meta->tables [i].base = (char*)p;
4718 for (row = 1; row <= meta->tables [i].rows; ++row) {
4719 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4720 for (col = 0; col < assembly->tables [i].columns; ++col) {
4721 switch (mono_metadata_table_size (bitfield, col)) {
4723 *p++ = values [col];
4726 *p++ = values [col] & 0xff;
4727 *p++ = (values [col] >> 8) & 0xff;
4730 *p++ = values [col] & 0xff;
4731 *p++ = (values [col] >> 8) & 0xff;
4732 *p++ = (values [col] >> 16) & 0xff;
4733 *p++ = (values [col] >> 24) & 0xff;
4736 g_assert_not_reached ();
4740 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4743 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4744 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4745 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4746 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4747 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4749 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4755 * Some tables in metadata need to be sorted according to some criteria, but
4756 * when methods and fields are first created with reflection, they may be assigned a token
4757 * that doesn't correspond to the final token they will get assigned after the sorting.
4758 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4759 * with the reflection objects that represent them. Once all the tables are set up, the
4760 * reflection objects will contains the correct table index. fixup_method() will fixup the
4761 * tokens for the method with ILGenerator @ilgen.
4764 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4766 guint32 code_idx = GPOINTER_TO_UINT (value);
4767 MonoReflectionILTokenInfo *iltoken;
4768 MonoReflectionFieldBuilder *field;
4769 MonoReflectionCtorBuilder *ctor;
4770 MonoReflectionMethodBuilder *method;
4771 MonoReflectionTypeBuilder *tb;
4772 MonoReflectionArrayMethod *am;
4774 unsigned char *target;
4776 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4777 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4778 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4779 switch (target [3]) {
4780 case MONO_TABLE_FIELD:
4781 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4782 field = (MonoReflectionFieldBuilder *)iltoken->member;
4783 idx = field->table_idx;
4784 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4785 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4786 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4788 g_assert_not_reached ();
4791 case MONO_TABLE_METHOD:
4792 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4793 method = (MonoReflectionMethodBuilder *)iltoken->member;
4794 idx = method->table_idx;
4795 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4796 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4797 idx = ctor->table_idx;
4798 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4799 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4800 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4801 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4803 g_assert_not_reached ();
4806 case MONO_TABLE_TYPEDEF:
4807 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4808 g_assert_not_reached ();
4809 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4810 idx = tb->table_idx;
4812 case MONO_TABLE_MEMBERREF:
4813 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4814 am = (MonoReflectionArrayMethod*)iltoken->member;
4815 idx = am->table_idx;
4816 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4817 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4818 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4819 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4820 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4821 g_assert (m->klass->generic_class || m->klass->generic_container);
4823 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4825 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4826 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4827 g_assert (is_field_on_inst (f));
4829 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4830 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4832 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4834 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4836 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4839 g_assert_not_reached ();
4842 case MONO_TABLE_METHODSPEC:
4843 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4844 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4845 g_assert (mono_method_signature (m)->generic_param_count);
4847 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4849 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4852 g_assert_not_reached ();
4856 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4858 target [0] = idx & 0xff;
4859 target [1] = (idx >> 8) & 0xff;
4860 target [2] = (idx >> 16) & 0xff;
4867 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4868 * value is not known when the table is emitted.
4871 fixup_cattrs (MonoDynamicImage *assembly)
4873 MonoDynamicTable *table;
4875 guint32 type, i, idx, token;
4878 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4880 for (i = 0; i < table->rows; ++i) {
4881 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4883 type = values [MONO_CUSTOM_ATTR_TYPE];
4884 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4885 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4886 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4887 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4890 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4891 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4892 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4893 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4894 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4895 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4896 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4897 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4904 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4906 MonoDynamicTable *table;
4909 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4911 alloc_table (table, table->rows);
4912 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4913 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4914 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4915 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4916 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4921 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4923 MonoDynamicTable *table;
4927 char *b = blob_size;
4929 guint32 idx, offset;
4931 if (rsrc->filename) {
4932 name = mono_string_to_utf8 (rsrc->filename);
4933 sname = g_path_get_basename (name);
4935 table = &assembly->tables [MONO_TABLE_FILE];
4937 alloc_table (table, table->rows);
4938 values = table->values + table->next_idx * MONO_FILE_SIZE;
4939 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4940 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4943 mono_sha1_get_digest_from_file (name, hash);
4944 mono_metadata_encode_value (20, b, &b);
4945 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4946 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4948 idx = table->next_idx++;
4950 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4956 data = mono_array_addr (rsrc->data, char, 0);
4957 len = mono_array_length (rsrc->data);
4963 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4964 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4965 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4966 mono_image_add_stream_data (&assembly->resources, data, len);
4970 * The entry should be emitted into the MANIFESTRESOURCE table of
4971 * the main module, but that needs to reference the FILE table
4972 * which isn't emitted yet.
4979 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4983 set_version_from_string (MonoString *version, guint32 *values)
4985 gchar *ver, *p, *str;
4988 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4989 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4990 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4991 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4994 ver = str = mono_string_to_utf8 (version);
4995 for (i = 0; i < 4; ++i) {
4996 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5002 /* handle Revision and Build */
5012 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5016 char *b = blob_size;
5021 len = mono_array_length (pkey);
5022 mono_metadata_encode_value (len, b, &b);
5023 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5024 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5026 assembly->public_key = (guint8 *)g_malloc (len);
5027 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5028 assembly->public_key_len = len;
5030 /* Special case: check for ECMA key (16 bytes) */
5031 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5032 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5033 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5034 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5035 /* minimum key size (in 2.0) is 384 bits */
5036 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5038 /* FIXME - verifier */
5039 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5040 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5042 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5048 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5050 MonoDynamicTable *table;
5051 MonoDynamicImage *assembly;
5052 MonoReflectionAssemblyBuilder *assemblyb;
5056 guint32 module_index;
5058 assemblyb = moduleb->assemblyb;
5059 assembly = moduleb->dynamic_image;
5060 domain = mono_object_domain (assemblyb);
5062 /* Emit ASSEMBLY table */
5063 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5064 alloc_table (table, 1);
5065 values = table->values + MONO_ASSEMBLY_SIZE;
5066 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5067 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5068 if (assemblyb->culture) {
5069 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5071 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5073 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5074 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5075 set_version_from_string (assemblyb->version, values);
5077 /* Emit FILE + EXPORTED_TYPE table */
5079 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5081 MonoReflectionModuleBuilder *file_module =
5082 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5083 if (file_module != moduleb) {
5084 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5086 if (file_module->types) {
5087 for (j = 0; j < file_module->num_types; ++j) {
5088 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5089 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5094 if (assemblyb->loaded_modules) {
5095 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5096 MonoReflectionModule *file_module =
5097 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5098 mono_image_fill_file_table (domain, file_module, assembly);
5100 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5103 if (assemblyb->type_forwarders)
5104 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5106 /* Emit MANIFESTRESOURCE table */
5108 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5110 MonoReflectionModuleBuilder *file_module =
5111 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5112 /* The table for the main module is emitted later */
5113 if (file_module != moduleb) {
5115 if (file_module->resources) {
5116 int len = mono_array_length (file_module->resources);
5117 for (j = 0; j < len; ++j) {
5118 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5119 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5126 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5129 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5130 * for the modulebuilder @moduleb.
5131 * At the end of the process, method and field tokens are fixed up and the
5132 * on-disk compressed metadata representation is created.
5133 * Return TRUE on success, or FALSE on failure and sets @error
5136 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5138 MonoDynamicTable *table;
5139 MonoDynamicImage *assembly;
5140 MonoReflectionAssemblyBuilder *assemblyb;
5146 mono_error_init (error);
5148 assemblyb = moduleb->assemblyb;
5149 assembly = moduleb->dynamic_image;
5150 domain = mono_object_domain (assemblyb);
5152 if (assembly->text_rva)
5155 assembly->text_rva = START_TEXT_RVA;
5157 if (moduleb->is_main) {
5158 mono_image_emit_manifest (moduleb);
5161 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5162 table->rows = 1; /* .<Module> */
5164 alloc_table (table, table->rows);
5166 * Set the first entry.
5168 values = table->values + table->columns;
5169 values [MONO_TYPEDEF_FLAGS] = 0;
5170 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5171 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5172 values [MONO_TYPEDEF_EXTENDS] = 0;
5173 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5174 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5177 * handle global methods
5178 * FIXME: test what to do when global methods are defined in multiple modules.
5180 if (moduleb->global_methods) {
5181 table = &assembly->tables [MONO_TABLE_METHOD];
5182 table->rows += mono_array_length (moduleb->global_methods);
5183 alloc_table (table, table->rows);
5184 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5185 if (!mono_image_get_method_info (
5186 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5190 if (moduleb->global_fields) {
5191 table = &assembly->tables [MONO_TABLE_FIELD];
5192 table->rows += mono_array_length (moduleb->global_fields);
5193 alloc_table (table, table->rows);
5194 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5195 mono_image_get_field_info (
5196 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5203 table = &assembly->tables [MONO_TABLE_MODULE];
5204 alloc_table (table, 1);
5205 mono_image_fill_module_table (domain, moduleb, assembly);
5207 /* Collect all types into a list sorted by their table_idx */
5208 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5211 for (i = 0; i < moduleb->num_types; ++i) {
5212 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5213 collect_types (&types, type);
5216 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5217 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5218 table->rows += mono_ptr_array_size (types);
5219 alloc_table (table, table->rows);
5222 * Emit type names + namespaces at one place inside the string heap,
5223 * so load_class_names () needs to touch fewer pages.
5225 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5226 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5227 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5229 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5230 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5231 string_heap_insert_mstring (&assembly->sheap, tb->name);
5234 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5235 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5236 if (!mono_image_get_type_info (domain, type, assembly, error))
5241 * table->rows is already set above and in mono_image_fill_module_table.
5243 /* add all the custom attributes at the end, once all the indexes are stable */
5244 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5247 /* CAS assembly permissions */
5248 if (assemblyb->permissions_minimum)
5249 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5250 if (assemblyb->permissions_optional)
5251 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5252 if (assemblyb->permissions_refused)
5253 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5255 if (!module_add_cattrs (assembly, moduleb, error))
5259 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5261 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5262 * the final tokens and don't need another fixup pass. */
5264 if (moduleb->global_methods) {
5265 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5266 MonoReflectionMethodBuilder *mb = mono_array_get (
5267 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5268 if (!mono_image_add_methodimpl (assembly, mb, error))
5273 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5274 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5275 if (type->methods) {
5276 for (j = 0; j < type->num_methods; ++j) {
5277 MonoReflectionMethodBuilder *mb = mono_array_get (
5278 type->methods, MonoReflectionMethodBuilder*, j);
5280 if (!mono_image_add_methodimpl (assembly, mb, error))
5286 fixup_cattrs (assembly);
5289 mono_ptr_array_destroy (types);
5292 return mono_error_ok (error);
5295 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5298 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5300 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5303 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5307 guint32 import_lookup_table;
5311 guint32 import_address_table_rva;
5319 #ifndef DISABLE_REFLECTION_EMIT
5322 * mono_image_insert_string:
5323 * @module: module builder object
5326 * Insert @str into the user string stream of @module.
5329 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5331 MonoDynamicImage *assembly;
5336 if (!module->dynamic_image)
5337 mono_image_module_basic_init (module);
5339 assembly = module->dynamic_image;
5341 if (assembly->save) {
5342 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5343 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5344 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5346 char *swapped = g_malloc (2 * mono_string_length (str));
5347 const char *p = (const char*)mono_string_chars (str);
5349 swap_with_size (swapped, p, 2, mono_string_length (str));
5350 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5354 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5356 mono_image_add_stream_data (&assembly->us, "", 1);
5358 idx = assembly->us.index ++;
5361 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5363 return MONO_TOKEN_STRING | idx;
5367 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5371 MonoMethodSignature *sig;
5373 mono_error_init (error);
5375 klass = obj->vtable->klass;
5376 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5377 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5378 MonoMethodSignature *old;
5379 guint32 sig_token, parent;
5382 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5384 nargs = mono_array_length (opt_param_types);
5385 old = mono_method_signature (method);
5386 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5388 sig->hasthis = old->hasthis;
5389 sig->explicit_this = old->explicit_this;
5390 sig->call_convention = old->call_convention;
5391 sig->generic_param_count = old->generic_param_count;
5392 sig->param_count = old->param_count + nargs;
5393 sig->sentinelpos = old->param_count;
5394 sig->ret = old->ret;
5396 for (i = 0; i < old->param_count; i++)
5397 sig->params [i] = old->params [i];
5399 for (i = 0; i < nargs; i++) {
5400 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5401 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5402 if (!is_ok (error)) goto fail;
5405 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5406 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5407 parent >>= MONO_TYPEDEFORREF_BITS;
5409 parent <<= MONO_MEMBERREF_PARENT_BITS;
5410 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5412 sig_token = method_encode_signature (assembly, sig);
5413 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5414 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5415 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5416 ReflectionMethodBuilder rmb;
5417 guint32 parent, sig_token;
5418 int nopt_args, nparams, ngparams, i;
5420 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5423 rmb.opt_types = opt_param_types;
5424 nopt_args = mono_array_length (opt_param_types);
5426 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5427 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5428 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5430 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5431 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5432 sig->call_convention = rmb.call_conv;
5433 sig->generic_param_count = ngparams;
5434 sig->param_count = nparams + nopt_args;
5435 sig->sentinelpos = nparams;
5436 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5437 if (!is_ok (error)) goto fail;
5439 for (i = 0; i < nparams; i++) {
5440 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5441 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5442 if (!is_ok (error)) goto fail;
5445 for (i = 0; i < nopt_args; i++) {
5446 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5447 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5448 if (!is_ok (error)) goto fail;
5451 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5455 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5456 if (!mono_error_ok (error))
5458 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5460 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5461 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5463 char *name = mono_string_to_utf8 (rmb.name);
5464 token = mono_image_get_varargs_method_token (
5465 assembly, parent, name, sig_token);
5468 g_error ("requested method token for %s\n", klass->name);
5471 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5472 register_dyn_token (assembly, token, obj);
5475 g_assert (!mono_error_ok (error));
5480 * mono_image_create_token:
5481 * @assembly: a dynamic assembly
5483 * @register_token: Whenever to register the token in the assembly->tokens hash.
5485 * Get a token to insert in the IL code stream for the given MemberInfo.
5486 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5487 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5491 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5492 gboolean create_open_instance, gboolean register_token,
5498 mono_error_init (error);
5500 klass = obj->vtable->klass;
5502 /* Check for user defined reflection objects */
5503 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5504 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5505 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5509 if (strcmp (klass->name, "MethodBuilder") == 0) {
5510 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5511 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5513 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5514 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5516 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5517 if (!mono_error_ok (error))
5520 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5521 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5522 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5523 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5525 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5526 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5528 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5529 if (!mono_error_ok (error))
5532 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5533 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5534 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5535 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5536 if (tb->generic_params) {
5537 token = mono_image_get_generic_field_token (assembly, fb);
5539 if (tb->module->dynamic_image == assembly) {
5540 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5542 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5545 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5546 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5547 if (create_open_instance && tb->generic_params) {
5549 init_type_builder_generics (obj);
5550 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5551 return_val_if_nok (error, 0);
5552 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5553 token = mono_metadata_token_from_dor (token);
5554 } else if (tb->module->dynamic_image == assembly) {
5555 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5558 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5559 return_val_if_nok (error, 0);
5560 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5562 } else if (strcmp (klass->name, "MonoType") == 0) {
5563 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5564 return_val_if_nok (error, 0);
5565 MonoClass *mc = mono_class_from_mono_type (type);
5566 token = mono_metadata_token_from_dor (
5567 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5568 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5569 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5570 return_val_if_nok (error, 0);
5571 token = mono_metadata_token_from_dor (
5572 mono_image_typedef_or_ref (assembly, type));
5573 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5574 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5575 return_val_if_nok (error, 0);
5576 token = mono_metadata_token_from_dor (
5577 mono_image_typedef_or_ref (assembly, type));
5578 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5579 strcmp (klass->name, "MonoMethod") == 0 ||
5580 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5581 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5582 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5583 if (m->method->is_inflated) {
5584 if (create_open_instance)
5585 token = mono_image_get_methodspec_token (assembly, m->method);
5587 token = mono_image_get_inflated_method_token (assembly, m->method);
5588 } else if ((m->method->klass->image == &assembly->image) &&
5589 !m->method->klass->generic_class) {
5590 static guint32 method_table_idx = 0xffffff;
5591 if (m->method->klass->wastypebuilder) {
5592 /* we use the same token as the one that was assigned
5593 * to the Methodbuilder.
5594 * FIXME: do the equivalent for Fields.
5596 token = m->method->token;
5599 * Each token should have a unique index, but the indexes are
5600 * assigned by managed code, so we don't know about them. An
5601 * easy solution is to count backwards...
5603 method_table_idx --;
5604 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5607 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5609 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5610 } else if (strcmp (klass->name, "MonoField") == 0) {
5611 MonoReflectionField *f = (MonoReflectionField *)obj;
5612 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5613 static guint32 field_table_idx = 0xffffff;
5615 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5617 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5619 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5620 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5621 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5622 token = mono_image_get_array_token (assembly, m);
5623 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5624 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5625 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5626 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5627 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5628 return_val_if_nok (error, 0);
5629 token = mono_metadata_token_from_dor (
5630 mono_image_typedef_or_ref (assembly, type));
5631 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5632 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5633 token = mono_image_get_field_on_inst_token (assembly, f, error);
5634 return_val_if_nok (error, 0);
5635 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5636 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5637 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5638 if (!mono_error_ok (error))
5640 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5641 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5642 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5643 if (!mono_error_ok (error))
5645 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5646 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5647 return_val_if_nok (error, 0);
5648 token = mono_metadata_token_from_dor (
5649 mono_image_typedef_or_ref (assembly, type));
5651 g_error ("requested token for %s\n", klass->name);
5655 mono_image_register_token (assembly, token, obj);
5661 * mono_image_register_token:
5663 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5664 * the Module.ResolveXXXToken () methods to work.
5667 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5671 dynamic_image_lock (assembly);
5672 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5674 /* There could be multiple MethodInfo objects with the same token */
5675 //g_assert (prev == obj);
5677 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5679 dynamic_image_unlock (assembly);
5682 static MonoDynamicImage*
5683 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5685 static const guchar entrycode [16] = {0xff, 0x25, 0};
5686 MonoDynamicImage *image;
5689 const char *version;
5691 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5692 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5694 version = mono_get_runtime_info ()->runtime_version;
5697 /* The MonoGHashTable's need GC tracking */
5698 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5700 image = g_new0 (MonoDynamicImage, 1);
5703 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5705 /*g_print ("created image %p\n", image);*/
5706 /* keep in sync with image.c */
5707 image->image.name = assembly_name;
5708 image->image.assembly_name = image->image.name; /* they may be different */
5709 image->image.module_name = module_name;
5710 image->image.version = g_strdup (version);
5711 image->image.md_version_major = 1;
5712 image->image.md_version_minor = 1;
5713 image->image.dynamic = TRUE;
5715 image->image.references = g_new0 (MonoAssembly*, 1);
5716 image->image.references [0] = NULL;
5718 mono_image_init (&image->image);
5720 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");
5721 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5722 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5723 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5724 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5725 image->handleref = g_hash_table_new (NULL, NULL);
5726 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");
5727 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5728 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");
5729 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");
5730 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5731 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5732 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5733 image->gen_params = g_ptr_array_new ();
5734 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5736 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5737 string_heap_init (&image->sheap);
5738 mono_image_add_stream_data (&image->us, "", 1);
5739 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5740 /* import tables... */
5741 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5742 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5743 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5744 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5745 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5746 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5747 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5748 stream_data_align (&image->code);
5750 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5752 for (i=0; i < MONO_TABLE_NUM; ++i) {
5753 image->tables [i].next_idx = 1;
5754 image->tables [i].columns = table_sizes [i];
5757 image->image.assembly = (MonoAssembly*)assembly;
5758 image->run = assembly->run;
5759 image->save = assembly->save;
5760 image->pe_kind = 0x1; /* ILOnly */
5761 image->machine = 0x14c; /* I386 */
5763 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5765 dynamic_images_lock ();
5767 if (!dynamic_images)
5768 dynamic_images = g_ptr_array_new ();
5770 g_ptr_array_add (dynamic_images, image);
5772 dynamic_images_unlock ();
5779 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5785 release_hashtable (MonoGHashTable **hash)
5788 mono_g_hash_table_destroy (*hash);
5794 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5796 release_hashtable (&image->token_fixups);
5797 release_hashtable (&image->handleref_managed);
5798 release_hashtable (&image->tokens);
5799 release_hashtable (&image->remapped_tokens);
5800 release_hashtable (&image->generic_def_objects);
5801 release_hashtable (&image->methodspec);
5804 // Free dynamic image pass one: Free resources but not image itself
5806 mono_dynamic_image_free (MonoDynamicImage *image)
5808 MonoDynamicImage *di = image;
5813 mono_g_hash_table_destroy (di->methodspec);
5815 g_hash_table_destroy (di->typespec);
5817 g_hash_table_destroy (di->typeref);
5819 g_hash_table_destroy (di->handleref);
5820 if (di->handleref_managed)
5821 mono_g_hash_table_destroy (di->handleref_managed);
5823 mono_g_hash_table_destroy (di->tokens);
5824 if (di->remapped_tokens)
5825 mono_g_hash_table_destroy (di->remapped_tokens);
5826 if (di->generic_def_objects)
5827 mono_g_hash_table_destroy (di->generic_def_objects);
5828 if (di->blob_cache) {
5829 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5830 g_hash_table_destroy (di->blob_cache);
5832 if (di->standalonesig_cache)
5833 g_hash_table_destroy (di->standalonesig_cache);
5834 for (list = di->array_methods; list; list = list->next) {
5835 ArrayMethod *am = (ArrayMethod *)list->data;
5840 g_list_free (di->array_methods);
5841 if (di->gen_params) {
5842 for (i = 0; i < di->gen_params->len; i++) {
5843 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5844 mono_gc_deregister_root ((char*) &entry->gparam);
5847 g_ptr_array_free (di->gen_params, TRUE);
5849 if (di->token_fixups)
5850 mono_g_hash_table_destroy (di->token_fixups);
5851 if (di->method_to_table_idx)
5852 g_hash_table_destroy (di->method_to_table_idx);
5853 if (di->field_to_table_idx)
5854 g_hash_table_destroy (di->field_to_table_idx);
5855 if (di->method_aux_hash)
5856 g_hash_table_destroy (di->method_aux_hash);
5857 if (di->vararg_aux_hash)
5858 g_hash_table_destroy (di->vararg_aux_hash);
5859 g_free (di->strong_name);
5860 g_free (di->win32_res);
5862 g_free (di->public_key);
5864 /*g_print ("string heap destroy for image %p\n", di);*/
5865 mono_dynamic_stream_reset (&di->sheap);
5866 mono_dynamic_stream_reset (&di->code);
5867 mono_dynamic_stream_reset (&di->resources);
5868 mono_dynamic_stream_reset (&di->us);
5869 mono_dynamic_stream_reset (&di->blob);
5870 mono_dynamic_stream_reset (&di->tstream);
5871 mono_dynamic_stream_reset (&di->guid);
5872 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5873 g_free (di->tables [i].values);
5876 dynamic_images_lock ();
5879 g_ptr_array_remove (dynamic_images, di);
5881 dynamic_images_unlock ();
5884 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5886 mono_dynamic_image_free_image (MonoDynamicImage *image)
5888 /* See create_dynamic_mono_image () */
5890 /* Allocated using GC_MALLOC */
5896 #ifndef DISABLE_REFLECTION_EMIT
5899 * mono_image_basic_init:
5900 * @assembly: an assembly builder object
5902 * Create the MonoImage that represents the assembly builder and setup some
5903 * of the helper hash table and the basic metadata streams.
5906 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5908 MonoDynamicAssembly *assembly;
5909 MonoDynamicImage *image;
5910 MonoDomain *domain = mono_object_domain (assemblyb);
5912 if (assemblyb->dynamic_assembly)
5916 /* assembly->assembly.image might be GC allocated */
5917 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5919 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5922 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5924 assembly->assembly.ref_count = 1;
5925 assembly->assembly.dynamic = TRUE;
5926 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5927 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5928 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5929 if (assemblyb->culture)
5930 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5932 assembly->assembly.aname.culture = g_strdup ("");
5934 if (assemblyb->version) {
5935 char *vstr = mono_string_to_utf8 (assemblyb->version);
5936 char **version = g_strsplit (vstr, ".", 4);
5937 char **parts = version;
5938 assembly->assembly.aname.major = atoi (*parts++);
5939 assembly->assembly.aname.minor = atoi (*parts++);
5940 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5941 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5943 g_strfreev (version);
5946 assembly->assembly.aname.major = 0;
5947 assembly->assembly.aname.minor = 0;
5948 assembly->assembly.aname.build = 0;
5949 assembly->assembly.aname.revision = 0;
5952 assembly->run = assemblyb->access != 2;
5953 assembly->save = assemblyb->access != 1;
5954 assembly->domain = domain;
5956 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5957 image->initial_image = TRUE;
5958 assembly->assembly.aname.name = image->image.name;
5959 assembly->assembly.image = &image->image;
5960 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5961 /* -1 to correct for the trailing NULL byte */
5962 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5963 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5965 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5968 mono_domain_assemblies_lock (domain);
5969 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5970 mono_domain_assemblies_unlock (domain);
5972 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5974 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5976 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5979 #endif /* !DISABLE_REFLECTION_EMIT */
5981 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5984 calc_section_size (MonoDynamicImage *assembly)
5988 /* alignment constraints */
5989 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5990 g_assert ((assembly->code.index % 4) == 0);
5991 assembly->meta_size += 3;
5992 assembly->meta_size &= ~3;
5993 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5994 g_assert ((assembly->resources.index % 4) == 0);
5996 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5997 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6000 if (assembly->win32_res) {
6001 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6003 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6004 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6008 assembly->sections [MONO_SECTION_RELOC].size = 12;
6009 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6019 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6023 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6025 ResTreeNode *t1 = (ResTreeNode*)a;
6026 ResTreeNode *t2 = (ResTreeNode*)b;
6028 return t1->id - t2->id;
6032 * resource_tree_create:
6034 * Organize the resources into a resource tree.
6036 static ResTreeNode *
6037 resource_tree_create (MonoArray *win32_resources)
6039 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6043 tree = g_new0 (ResTreeNode, 1);
6045 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6046 MonoReflectionWin32Resource *win32_res =
6047 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6051 /* FIXME: BUG: this stores managed references in unmanaged memory */
6052 lang_node = g_new0 (ResTreeNode, 1);
6053 lang_node->id = win32_res->lang_id;
6054 lang_node->win32_res = win32_res;
6056 /* Create type node if neccesary */
6058 for (l = tree->children; l; l = l->next)
6059 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6060 type_node = (ResTreeNode*)l->data;
6065 type_node = g_new0 (ResTreeNode, 1);
6066 type_node->id = win32_res->res_type;
6069 * The resource types have to be sorted otherwise
6070 * Windows Explorer can't display the version information.
6072 tree->children = g_slist_insert_sorted (tree->children,
6073 type_node, resource_tree_compare_by_id);
6076 /* Create res node if neccesary */
6078 for (l = type_node->children; l; l = l->next)
6079 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6080 res_node = (ResTreeNode*)l->data;
6085 res_node = g_new0 (ResTreeNode, 1);
6086 res_node->id = win32_res->res_id;
6087 type_node->children = g_slist_append (type_node->children, res_node);
6090 res_node->children = g_slist_append (res_node->children, lang_node);
6097 * resource_tree_encode:
6099 * Encode the resource tree into the format used in the PE file.
6102 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6105 MonoPEResourceDir dir;
6106 MonoPEResourceDirEntry dir_entry;
6107 MonoPEResourceDataEntry data_entry;
6109 guint32 res_id_entries;
6112 * For the format of the resource directory, see the article
6113 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6117 memset (&dir, 0, sizeof (dir));
6118 memset (&dir_entry, 0, sizeof (dir_entry));
6119 memset (&data_entry, 0, sizeof (data_entry));
6121 g_assert (sizeof (dir) == 16);
6122 g_assert (sizeof (dir_entry) == 8);
6123 g_assert (sizeof (data_entry) == 16);
6125 node->offset = p - begin;
6127 /* IMAGE_RESOURCE_DIRECTORY */
6128 res_id_entries = g_slist_length (node->children);
6129 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6131 memcpy (p, &dir, sizeof (dir));
6134 /* Reserve space for entries */
6136 p += sizeof (dir_entry) * res_id_entries;
6138 /* Write children */
6139 for (l = node->children; l; l = l->next) {
6140 ResTreeNode *child = (ResTreeNode*)l->data;
6142 if (child->win32_res) {
6145 child->offset = p - begin;
6147 /* IMAGE_RESOURCE_DATA_ENTRY */
6148 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6149 size = mono_array_length (child->win32_res->res_data);
6150 data_entry.rde_size = GUINT32_TO_LE (size);
6152 memcpy (p, &data_entry, sizeof (data_entry));
6153 p += sizeof (data_entry);
6155 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6158 resource_tree_encode (child, begin, p, &p);
6162 /* IMAGE_RESOURCE_ENTRY */
6163 for (l = node->children; l; l = l->next) {
6164 ResTreeNode *child = (ResTreeNode*)l->data;
6166 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6167 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6169 memcpy (entries, &dir_entry, sizeof (dir_entry));
6170 entries += sizeof (dir_entry);
6177 resource_tree_free (ResTreeNode * node)
6180 for (list = node->children; list; list = list->next)
6181 resource_tree_free ((ResTreeNode*)list->data);
6182 g_slist_free(node->children);
6187 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6192 MonoReflectionWin32Resource *win32_res;
6195 if (!assemblyb->win32_resources)
6199 * Resources are stored in a three level tree inside the PE file.
6200 * - level one contains a node for each type of resource
6201 * - level two contains a node for each resource
6202 * - level three contains a node for each instance of a resource for a
6203 * specific language.
6206 tree = resource_tree_create (assemblyb->win32_resources);
6208 /* Estimate the size of the encoded tree */
6210 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6211 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6212 size += mono_array_length (win32_res->res_data);
6214 /* Directory structure */
6215 size += mono_array_length (assemblyb->win32_resources) * 256;
6216 p = buf = (char *)g_malloc (size);
6218 resource_tree_encode (tree, p, p, &p);
6220 g_assert (p - buf <= size);
6222 assembly->win32_res = (char *)g_malloc (p - buf);
6223 assembly->win32_res_size = p - buf;
6224 memcpy (assembly->win32_res, buf, p - buf);
6227 resource_tree_free (tree);
6231 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6233 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6236 p += sizeof (MonoPEResourceDir);
6237 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6238 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6239 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6240 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6241 fixup_resource_directory (res_section, child, rva);
6243 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6244 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6247 p += sizeof (MonoPEResourceDirEntry);
6252 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6255 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6256 g_error ("WriteFile returned %d\n", GetLastError ());
6260 * mono_image_create_pefile:
6261 * @mb: a module builder object
6263 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6264 * assembly->pefile where it can be easily retrieved later in chunks.
6267 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6269 MonoMSDOSHeader *msdos;
6270 MonoDotNetHeader *header;
6271 MonoSectionTable *section;
6272 MonoCLIHeader *cli_header;
6273 guint32 size, image_size, virtual_base, text_offset;
6274 guint32 header_start, section_start, file_offset, virtual_offset;
6275 MonoDynamicImage *assembly;
6276 MonoReflectionAssemblyBuilder *assemblyb;
6277 MonoDynamicStream pefile_stream = {0};
6278 MonoDynamicStream *pefile = &pefile_stream;
6280 guint32 *rva, value;
6282 static const unsigned char msheader[] = {
6283 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6284 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6287 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6288 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6289 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6290 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6293 mono_error_init (error);
6295 assemblyb = mb->assemblyb;
6297 mono_image_basic_init (assemblyb);
6298 assembly = mb->dynamic_image;
6300 assembly->pe_kind = assemblyb->pe_kind;
6301 assembly->machine = assemblyb->machine;
6302 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6303 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6305 if (!mono_image_build_metadata (mb, error))
6309 if (mb->is_main && assemblyb->resources) {
6310 int len = mono_array_length (assemblyb->resources);
6311 for (i = 0; i < len; ++i)
6312 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6315 if (mb->resources) {
6316 int len = mono_array_length (mb->resources);
6317 for (i = 0; i < len; ++i)
6318 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6321 if (!build_compressed_metadata (assembly, error))
6325 assembly_add_win32_resources (assembly, assemblyb);
6327 nsections = calc_section_size (assembly);
6329 /* The DOS header and stub */
6330 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6331 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6333 /* the dotnet header */
6334 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6336 /* the section tables */
6337 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6339 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6340 virtual_offset = VIRT_ALIGN;
6343 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6344 if (!assembly->sections [i].size)
6347 file_offset += FILE_ALIGN - 1;
6348 file_offset &= ~(FILE_ALIGN - 1);
6349 virtual_offset += VIRT_ALIGN - 1;
6350 virtual_offset &= ~(VIRT_ALIGN - 1);
6352 assembly->sections [i].offset = file_offset;
6353 assembly->sections [i].rva = virtual_offset;
6355 file_offset += assembly->sections [i].size;
6356 virtual_offset += assembly->sections [i].size;
6357 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6360 file_offset += FILE_ALIGN - 1;
6361 file_offset &= ~(FILE_ALIGN - 1);
6363 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6365 /* back-patch info */
6366 msdos = (MonoMSDOSHeader*)pefile->data;
6367 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6369 header = (MonoDotNetHeader*)(pefile->data + header_start);
6370 header->pesig [0] = 'P';
6371 header->pesig [1] = 'E';
6373 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6374 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6375 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6376 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6377 if (assemblyb->pekind == 1) {
6379 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6382 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6385 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6387 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6388 header->pe.pe_major = 6;
6389 header->pe.pe_minor = 0;
6390 size = assembly->sections [MONO_SECTION_TEXT].size;
6391 size += FILE_ALIGN - 1;
6392 size &= ~(FILE_ALIGN - 1);
6393 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6394 size = assembly->sections [MONO_SECTION_RSRC].size;
6395 size += FILE_ALIGN - 1;
6396 size &= ~(FILE_ALIGN - 1);
6397 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6398 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6399 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6400 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6401 /* pe_rva_entry_point always at the beginning of the text section */
6402 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6404 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6405 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6406 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6407 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6408 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6409 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6410 size = section_start;
6411 size += FILE_ALIGN - 1;
6412 size &= ~(FILE_ALIGN - 1);
6413 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6415 size += VIRT_ALIGN - 1;
6416 size &= ~(VIRT_ALIGN - 1);
6417 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6420 // Translate the PEFileKind value to the value expected by the Windows loader
6426 // PEFileKinds.Dll == 1
6427 // PEFileKinds.ConsoleApplication == 2
6428 // PEFileKinds.WindowApplication == 3
6431 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6432 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6434 if (assemblyb->pekind == 3)
6439 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6441 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6442 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6443 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6444 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6445 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6446 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6448 /* fill data directory entries */
6450 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6451 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6453 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6454 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6456 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6457 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6458 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6459 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6460 /* patch entrypoint name */
6461 if (assemblyb->pekind == 1)
6462 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6464 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6465 /* patch imported function RVA name */
6466 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6467 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6469 /* the import table */
6470 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6471 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6472 /* patch imported dll RVA name and other entries in the dir */
6473 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6474 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6475 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6476 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6477 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6478 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6480 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6481 value = (assembly->text_rva + assembly->imp_names_offset);
6482 *p++ = (value) & 0xff;
6483 *p++ = (value >> 8) & (0xff);
6484 *p++ = (value >> 16) & (0xff);
6485 *p++ = (value >> 24) & (0xff);
6487 /* the CLI header info */
6488 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6489 cli_header->ch_size = GUINT32_FROM_LE (72);
6490 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6491 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6492 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6493 if (assemblyb->entry_point) {
6494 guint32 table_idx = 0;
6495 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6496 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6497 table_idx = methodb->table_idx;
6499 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6501 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6503 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6505 /* The embedded managed resources */
6506 text_offset = assembly->text_rva + assembly->code.index;
6507 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6508 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6509 text_offset += assembly->resources.index;
6510 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6511 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6512 text_offset += assembly->meta_size;
6513 if (assembly->strong_name_size) {
6514 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6515 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6516 text_offset += assembly->strong_name_size;
6519 /* write the section tables and section content */
6520 section = (MonoSectionTable*)(pefile->data + section_start);
6521 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6522 static const char section_names [][7] = {
6523 ".text", ".rsrc", ".reloc"
6525 if (!assembly->sections [i].size)
6527 strcpy (section->st_name, section_names [i]);
6528 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6529 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6530 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6531 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6532 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6533 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6534 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6538 checked_write_file (file, pefile->data, pefile->index);
6540 mono_dynamic_stream_reset (pefile);
6542 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6543 if (!assembly->sections [i].size)
6546 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6547 g_error ("SetFilePointer returned %d\n", GetLastError ());
6550 case MONO_SECTION_TEXT:
6551 /* patch entry point */
6552 p = (guchar*)(assembly->code.data + 2);
6553 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6554 *p++ = (value) & 0xff;
6555 *p++ = (value >> 8) & 0xff;
6556 *p++ = (value >> 16) & 0xff;
6557 *p++ = (value >> 24) & 0xff;
6559 checked_write_file (file, assembly->code.data, assembly->code.index);
6560 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6561 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6562 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6565 g_free (assembly->image.raw_metadata);
6567 case MONO_SECTION_RELOC: {
6571 guint16 type_and_offset;
6575 g_assert (sizeof (reloc) == 12);
6577 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6578 reloc.block_size = GUINT32_FROM_LE (12);
6581 * the entrypoint is always at the start of the text section
6582 * 3 is IMAGE_REL_BASED_HIGHLOW
6583 * 2 is patch_size_rva - text_rva
6585 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6588 checked_write_file (file, &reloc, sizeof (reloc));
6592 case MONO_SECTION_RSRC:
6593 if (assembly->win32_res) {
6595 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6596 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6597 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6601 g_assert_not_reached ();
6605 /* check that the file is properly padded */
6606 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6607 g_error ("SetFilePointer returned %d\n", GetLastError ());
6608 if (! SetEndOfFile (file))
6609 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6611 mono_dynamic_stream_reset (&assembly->code);
6612 mono_dynamic_stream_reset (&assembly->us);
6613 mono_dynamic_stream_reset (&assembly->blob);
6614 mono_dynamic_stream_reset (&assembly->guid);
6615 mono_dynamic_stream_reset (&assembly->sheap);
6617 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6618 g_hash_table_destroy (assembly->blob_cache);
6619 assembly->blob_cache = NULL;
6624 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6627 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6629 g_assert_not_reached ();
6632 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6634 #ifndef DISABLE_REFLECTION_EMIT
6636 MonoReflectionModule *
6637 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6640 MonoReflectionModule *result = NULL;
6643 MonoImageOpenStatus status;
6644 MonoDynamicAssembly *assembly;
6645 guint32 module_count;
6646 MonoImage **new_modules;
6647 gboolean *new_modules_loaded;
6649 name = mono_string_to_utf8 (fileName);
6651 image = mono_image_open (name, &status);
6654 if (status == MONO_IMAGE_ERROR_ERRNO)
6655 exc = mono_get_exception_file_not_found (fileName);
6657 exc = mono_get_exception_bad_image_format (name);
6659 mono_raise_exception (exc);
6664 assembly = ab->dynamic_assembly;
6665 image->assembly = (MonoAssembly*)assembly;
6667 module_count = image->assembly->image->module_count;
6668 new_modules = g_new0 (MonoImage *, module_count + 1);
6669 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6671 if (image->assembly->image->modules)
6672 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6673 if (image->assembly->image->modules_loaded)
6674 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6675 new_modules [module_count] = image;
6676 new_modules_loaded [module_count] = TRUE;
6677 mono_image_addref (image);
6679 g_free (image->assembly->image->modules);
6680 image->assembly->image->modules = new_modules;
6681 image->assembly->image->modules_loaded = new_modules_loaded;
6682 image->assembly->image->module_count ++;
6684 mono_assembly_load_references (image, &status);
6686 mono_image_close (image);
6687 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6690 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6691 mono_error_raise_exception (&error); /* FIXME don't raise here */
6695 #endif /* DISABLE_REFLECTION_EMIT */
6698 * We need to return always the same object for MethodInfo, FieldInfo etc..
6699 * but we need to consider the reflected type.
6700 * type uses a different hash, since it uses custom hash/equal functions.
6705 MonoClass *refclass;
6709 reflected_equal (gconstpointer a, gconstpointer b) {
6710 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6711 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6713 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6717 reflected_hash (gconstpointer a) {
6718 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6719 return mono_aligned_addr_hash (ea->item);
6722 #define CHECK_OBJECT(t,p,k) \
6728 mono_domain_lock (domain); \
6729 if (!domain->refobject_hash) \
6730 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"); \
6731 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6732 mono_domain_unlock (domain); \
6735 mono_domain_unlock (domain); \
6738 #ifdef HAVE_BOEHM_GC
6739 /* ReflectedEntry doesn't need to be GC tracked */
6740 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6741 #define FREE_REFENTRY(entry) g_free ((entry))
6742 #define REFENTRY_REQUIRES_CLEANUP
6744 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6746 #define FREE_REFENTRY(entry)
6749 #define CACHE_OBJECT(t,p,o,k) \
6752 ReflectedEntry pe; \
6754 pe.refclass = (k); \
6755 mono_domain_lock (domain); \
6756 if (!domain->refobject_hash) \
6757 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"); \
6758 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6760 ReflectedEntry *e = ALLOC_REFENTRY; \
6762 e->refclass = (k); \
6763 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6766 mono_domain_unlock (domain); \
6771 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6773 mono_domain_lock (domain);
6774 if (domain->refobject_hash) {
6776 gpointer orig_pe, orig_value;
6779 pe.refclass = klass;
6780 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6781 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6782 FREE_REFENTRY (orig_pe);
6785 mono_domain_unlock (domain);
6788 #ifdef REFENTRY_REQUIRES_CLEANUP
6790 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6792 FREE_REFENTRY (key);
6797 mono_reflection_cleanup_domain (MonoDomain *domain)
6799 if (domain->refobject_hash) {
6800 /*let's avoid scanning the whole hashtable if not needed*/
6801 #ifdef REFENTRY_REQUIRES_CLEANUP
6802 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6804 mono_g_hash_table_destroy (domain->refobject_hash);
6805 domain->refobject_hash = NULL;
6809 #ifndef DISABLE_REFLECTION_EMIT
6811 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6813 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6817 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6819 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6823 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6825 MonoDynamicImage *image = moduleb->dynamic_image;
6826 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6830 MonoImage **new_modules;
6832 char *name, *fqname;
6834 * FIXME: we already created an image in mono_image_basic_init (), but
6835 * we don't know which module it belongs to, since that is only
6836 * determined at assembly save time.
6838 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6839 name = mono_string_to_utf8 (ab->name);
6840 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6841 if (!mono_error_ok (&error)) {
6843 mono_error_raise_exception (&error);
6845 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6847 moduleb->module.image = &image->image;
6848 moduleb->dynamic_image = image;
6849 register_module (mono_object_domain (moduleb), moduleb, image);
6851 /* register the module with the assembly */
6852 ass = ab->dynamic_assembly->assembly.image;
6853 module_count = ass->module_count;
6854 new_modules = g_new0 (MonoImage *, module_count + 1);
6857 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6858 new_modules [module_count] = &image->image;
6859 mono_image_addref (&image->image);
6861 g_free (ass->modules);
6862 ass->modules = new_modules;
6863 ass->module_count ++;
6868 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6870 MonoDynamicImage *image = moduleb->dynamic_image;
6872 g_assert (type->type);
6873 image->wrappers_type = mono_class_from_mono_type (type->type);
6879 * mono_assembly_get_object:
6880 * @domain: an app domain
6881 * @assembly: an assembly
6883 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6885 MonoReflectionAssembly*
6886 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6889 MonoReflectionAssembly *result;
6890 result = mono_assembly_get_object_checked (domain, assembly, &error);
6891 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6895 * mono_assembly_get_object_checked:
6896 * @domain: an app domain
6897 * @assembly: an assembly
6899 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6901 MonoReflectionAssembly*
6902 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6904 MonoReflectionAssembly *res;
6906 mono_error_init (error);
6908 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6909 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6912 res->assembly = assembly;
6914 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6919 MonoReflectionModule*
6920 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6923 MonoReflectionModule *result;
6924 result = mono_module_get_object_checked (domain, image, &error);
6925 mono_error_raise_exception (&error);
6929 MonoReflectionModule*
6930 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6932 MonoReflectionModule *res;
6935 mono_error_init (error);
6936 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6937 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6942 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6945 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6947 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6948 basename = g_path_get_basename (image->name);
6949 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6950 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6954 if (image->assembly->image == image) {
6955 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6959 if (image->assembly->image->modules) {
6960 for (i = 0; i < image->assembly->image->module_count; i++) {
6961 if (image->assembly->image->modules [i] == image)
6962 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6964 g_assert (res->token);
6968 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6971 MonoReflectionModule*
6972 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6975 MonoReflectionModule *result;
6976 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6977 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6981 MonoReflectionModule*
6982 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6984 MonoReflectionModule *res;
6985 MonoTableInfo *table;
6986 guint32 cols [MONO_FILE_SIZE];
6988 guint32 i, name_idx;
6991 mono_error_init (error);
6993 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6997 table = &image->tables [MONO_TABLE_FILE];
6998 g_assert (table_index < table->rows);
6999 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7002 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7005 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7006 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7008 /* Check whenever the row has a corresponding row in the moduleref table */
7009 table = &image->tables [MONO_TABLE_MODULEREF];
7010 for (i = 0; i < table->rows; ++i) {
7011 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7012 val = mono_metadata_string_heap (image, name_idx);
7013 if (strcmp (val, name) == 0)
7014 res->image = image->modules [i];
7017 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7018 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7019 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7020 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7021 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7027 verify_safe_for_managed_space (MonoType *type)
7029 switch (type->type) {
7031 case MONO_TYPE_ARRAY:
7032 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7034 return verify_safe_for_managed_space (type->data.type);
7035 case MONO_TYPE_SZARRAY:
7036 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7037 case MONO_TYPE_GENERICINST: {
7038 MonoGenericInst *inst = type->data.generic_class->inst;
7042 for (i = 0; i < inst->type_argc; ++i)
7043 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7049 case MONO_TYPE_MVAR:
7057 mono_type_normalize (MonoType *type)
7060 MonoGenericClass *gclass;
7061 MonoGenericInst *ginst;
7063 MonoGenericContainer *gcontainer;
7064 MonoType **argv = NULL;
7065 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7067 if (type->type != MONO_TYPE_GENERICINST)
7070 gclass = type->data.generic_class;
7071 ginst = gclass->context.class_inst;
7072 if (!ginst->is_open)
7075 gtd = gclass->container_class;
7076 gcontainer = gtd->generic_container;
7077 argv = g_newa (MonoType*, ginst->type_argc);
7079 for (i = 0; i < ginst->type_argc; ++i) {
7080 MonoType *t = ginst->type_argv [i], *norm;
7081 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7082 is_denorm_gtd = FALSE;
7083 norm = mono_type_normalize (t);
7086 requires_rebind = TRUE;
7090 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7092 if (requires_rebind) {
7093 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7094 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7100 * mono_type_get_object:
7101 * @domain: an app domain
7104 * Return an System.MonoType object representing the type @type.
7107 mono_type_get_object (MonoDomain *domain, MonoType *type)
7110 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7111 mono_error_raise_exception (&error);
7117 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7119 MonoType *norm_type;
7120 MonoReflectionType *res;
7123 mono_error_init (error);
7125 klass = mono_class_from_mono_type (type);
7127 /*we must avoid using @type as it might have come
7128 * from a mono_metadata_type_dup and the caller
7129 * expects that is can be freed.
7130 * Using the right type from
7132 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7134 /* void is very common */
7135 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7136 return (MonoReflectionType*)domain->typeof_void;
7139 * If the vtable of the given class was already created, we can use
7140 * the MonoType from there and avoid all locking and hash table lookups.
7142 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7143 * that the resulting object is different.
7145 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7146 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7147 if (vtable && vtable->type)
7148 return (MonoReflectionType *)vtable->type;
7151 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7152 mono_domain_lock (domain);
7153 if (!domain->type_hash)
7154 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7155 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7156 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7157 mono_domain_unlock (domain);
7158 mono_loader_unlock ();
7162 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7163 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7164 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7165 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7166 * artifact of how generics are encoded and should be transparent to managed code so we
7167 * need to weed out this diference when retrieving managed System.Type objects.
7169 norm_type = mono_type_normalize (type);
7170 if (norm_type != type) {
7171 res = mono_type_get_object_checked (domain, norm_type, error);
7172 if (!mono_error_ok (error))
7174 mono_g_hash_table_insert (domain->type_hash, type, res);
7175 mono_domain_unlock (domain);
7176 mono_loader_unlock ();
7180 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7181 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7184 if (!verify_safe_for_managed_space (type)) {
7185 mono_domain_unlock (domain);
7186 mono_loader_unlock ();
7187 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7191 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7192 gboolean is_type_done = TRUE;
7193 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7194 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7195 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7197 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7198 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7200 if (gparam->owner && gparam->owner->is_method) {
7201 MonoMethod *method = gparam->owner->owner.method;
7202 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7203 is_type_done = FALSE;
7204 } else if (gparam->owner && !gparam->owner->is_method) {
7205 MonoClass *klass = gparam->owner->owner.klass;
7206 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7207 is_type_done = FALSE;
7211 /* g_assert_not_reached (); */
7212 /* should this be considered an error condition? */
7213 if (is_type_done && !type->byref) {
7214 mono_domain_unlock (domain);
7215 mono_loader_unlock ();
7216 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7219 /* This is stored in vtables/JITted code so it has to be pinned */
7220 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7221 if (!mono_error_ok (error))
7225 mono_g_hash_table_insert (domain->type_hash, type, res);
7227 if (type->type == MONO_TYPE_VOID)
7228 domain->typeof_void = (MonoObject*)res;
7230 mono_domain_unlock (domain);
7231 mono_loader_unlock ();
7236 * mono_method_get_object:
7237 * @domain: an app domain
7239 * @refclass: the reflected type (can be NULL)
7241 * Return an System.Reflection.MonoMethod object representing the method @method.
7243 MonoReflectionMethod*
7244 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7247 MonoReflectionMethod *ret = NULL;
7248 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7249 mono_error_raise_exception (&error);
7254 * mono_method_get_object_checked:
7255 * @domain: an app domain
7257 * @refclass: the reflected type (can be NULL)
7258 * @error: set on error.
7260 * Return an System.Reflection.MonoMethod object representing the method @method.
7261 * Returns NULL and sets @error on error.
7263 MonoReflectionMethod*
7264 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7267 * We use the same C representation for methods and constructors, but the type
7268 * name in C# is different.
7270 MonoReflectionType *rt;
7272 MonoReflectionMethod *ret;
7274 mono_error_init (error);
7276 if (method->is_inflated) {
7277 MonoReflectionGenericMethod *gret;
7280 refclass = method->klass;
7281 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7282 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7283 klass = mono_class_get_mono_generic_cmethod_class ();
7285 klass = mono_class_get_mono_generic_method_class ();
7287 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7288 if (!mono_error_ok (error))
7290 gret->method.method = method;
7292 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7294 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7295 if (!mono_error_ok (error))
7298 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7300 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7304 refclass = method->klass;
7306 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7307 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7308 klass = mono_class_get_mono_cmethod_class ();
7311 klass = mono_class_get_mono_method_class ();
7313 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7314 if (!mono_error_ok (error))
7316 ret->method = method;
7318 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7319 if (!mono_error_ok (error))
7322 MONO_OBJECT_SETREF (ret, reftype, rt);
7324 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7327 g_assert (!mono_error_ok (error));
7332 * mono_method_clear_object:
7334 * Clear the cached reflection objects for the dynamic method METHOD.
7337 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7340 g_assert (method_is_dynamic (method));
7342 klass = method->klass;
7344 clear_cached_object (domain, method, klass);
7345 klass = klass->parent;
7347 /* Added by mono_param_get_objects () */
7348 clear_cached_object (domain, &(method->signature), NULL);
7349 klass = method->klass;
7351 clear_cached_object (domain, &(method->signature), klass);
7352 klass = klass->parent;
7357 * mono_field_get_object:
7358 * @domain: an app domain
7362 * Return an System.Reflection.MonoField object representing the field @field
7365 MonoReflectionField*
7366 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7369 MonoReflectionField *result;
7370 result = mono_field_get_object_checked (domain, klass, field, &error);
7371 mono_error_raise_exception (&error);
7376 * mono_field_get_object_checked:
7377 * @domain: an app domain
7380 * @error: set on error
7382 * Return an System.Reflection.MonoField object representing the field @field
7383 * in class @klass. On error, returns NULL and sets @error.
7385 MonoReflectionField*
7386 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7388 MonoReflectionType *rt;
7389 MonoReflectionField *res;
7391 mono_error_init (error);
7393 CHECK_OBJECT (MonoReflectionField *, field, klass);
7394 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7399 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7401 if (is_field_on_inst (field)) {
7402 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7404 rt = mono_type_get_object_checked (domain, field->type, error);
7405 if (!mono_error_ok (error))
7408 MONO_OBJECT_SETREF (res, type, rt);
7411 rt = mono_type_get_object_checked (domain, field->type, error);
7412 if (!mono_error_ok (error))
7415 MONO_OBJECT_SETREF (res, type, rt);
7417 res->attrs = mono_field_get_flags (field);
7419 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7423 * mono_property_get_object:
7424 * @domain: an app domain
7426 * @property: a property
7428 * Return an System.Reflection.MonoProperty object representing the property @property
7431 MonoReflectionProperty*
7432 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7435 MonoReflectionProperty *result;
7436 result = mono_property_get_object_checked (domain, klass, property, &error);
7437 mono_error_raise_exception (&error);
7442 * mono_property_get_object:
7443 * @domain: an app domain
7445 * @property: a property
7446 * @error: set on error
7448 * Return an System.Reflection.MonoProperty object representing the property @property
7449 * in class @klass. On error returns NULL and sets @error.
7451 MonoReflectionProperty*
7452 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7454 MonoReflectionProperty *res;
7456 mono_error_init (error);
7458 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7459 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7463 res->property = property;
7464 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7468 * mono_event_get_object:
7469 * @domain: an app domain
7473 * Return an System.Reflection.MonoEvent object representing the event @event
7476 MonoReflectionEvent*
7477 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7480 MonoReflectionEvent *result;
7481 result = mono_event_get_object_checked (domain, klass, event, &error);
7482 mono_error_raise_exception (&error);
7487 * mono_event_get_object_checked:
7488 * @domain: an app domain
7491 * @error: set on error
7493 * Return an System.Reflection.MonoEvent object representing the event @event
7494 * in class @klass. On failure sets @error and returns NULL
7496 MonoReflectionEvent*
7497 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7499 MonoReflectionEvent *res;
7500 MonoReflectionMonoEvent *mono_event;
7502 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7503 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7506 mono_event->klass = klass;
7507 mono_event->event = event;
7508 res = (MonoReflectionEvent*)mono_event;
7509 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7513 * mono_get_reflection_missing_object:
7514 * @domain: Domain where the object lives
7516 * Returns the System.Reflection.Missing.Value singleton object
7517 * (of type System.Reflection.Missing).
7519 * Used as the value for ParameterInfo.DefaultValue when Optional
7523 mono_get_reflection_missing_object (MonoDomain *domain)
7526 static MonoClassField *missing_value_field = NULL;
7528 if (!missing_value_field) {
7529 MonoClass *missing_klass;
7530 missing_klass = mono_class_get_missing_class ();
7531 mono_class_init (missing_klass);
7532 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7533 g_assert (missing_value_field);
7535 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7541 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7544 *dbnull = mono_get_dbnull_object (domain);
7549 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7551 if (!*reflection_missing)
7552 *reflection_missing = mono_get_reflection_missing_object (domain);
7553 return *reflection_missing;
7557 * mono_param_get_objects:
7558 * @domain: an app domain
7561 * Return an System.Reflection.ParameterInfo array object representing the parameters
7562 * in the method @method.
7565 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7567 static MonoClass *System_Reflection_ParameterInfo;
7568 static MonoClass *System_Reflection_ParameterInfo_array;
7570 MonoArray *res = NULL;
7571 MonoReflectionMethod *member = NULL;
7572 MonoReflectionParameter *param = NULL;
7573 char **names = NULL, **blobs = NULL;
7574 guint32 *types = NULL;
7575 MonoType *type = NULL;
7576 MonoObject *dbnull = NULL;
7577 MonoObject *missing = NULL;
7578 MonoMarshalSpec **mspecs = NULL;
7579 MonoMethodSignature *sig = NULL;
7580 MonoVTable *pinfo_vtable;
7581 MonoReflectionType *rt;
7584 mono_error_init (&error);
7586 if (!System_Reflection_ParameterInfo_array) {
7589 klass = mono_class_get_mono_parameter_info_class ();
7591 mono_memory_barrier ();
7592 System_Reflection_ParameterInfo = klass;
7595 klass = mono_array_class_get (klass, 1);
7596 mono_memory_barrier ();
7597 System_Reflection_ParameterInfo_array = klass;
7600 sig = mono_method_signature_checked (method, &error);
7601 if (!mono_error_ok (&error))
7604 if (!sig->param_count) {
7605 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7612 /* Note: the cache is based on the address of the signature into the method
7613 * since we already cache MethodInfos with the method as keys.
7615 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7617 member = mono_method_get_object_checked (domain, method, refclass, &error);
7620 names = g_new (char *, sig->param_count);
7621 mono_method_get_param_names (method, (const char **) names);
7623 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7624 mono_method_get_marshal_info (method, mspecs);
7626 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7630 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7631 for (i = 0; i < sig->param_count; ++i) {
7632 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7636 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7640 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7642 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7644 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7646 param->PositionImpl = i;
7647 param->AttrsImpl = sig->params [i]->attrs;
7649 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7650 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7651 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7653 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7657 blobs = g_new0 (char *, sig->param_count);
7658 types = g_new0 (guint32, sig->param_count);
7659 get_default_param_value_blobs (method, blobs, types);
7662 /* Build MonoType for the type from the Constant Table */
7664 type = g_new0 (MonoType, 1);
7665 type->type = (MonoTypeEnum)types [i];
7666 type->data.klass = NULL;
7667 if (types [i] == MONO_TYPE_CLASS)
7668 type->data.klass = mono_defaults.object_class;
7669 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7670 /* For enums, types [i] contains the base type */
7672 type->type = MONO_TYPE_VALUETYPE;
7673 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7675 type->data.klass = mono_class_from_mono_type (type);
7677 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7679 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7680 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7681 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7682 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7684 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7689 if (mspecs [i + 1]) {
7690 MonoReflectionMarshalAsAttribute* mobj;
7691 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7694 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7697 mono_array_setref (res, i, param);
7707 for (i = sig->param_count; i >= 0; i--) {
7709 mono_metadata_free_marshal_spec (mspecs [i]);
7714 mono_error_raise_exception (&error); /* FIXME don't raise here */
7716 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7720 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7722 return mono_param_get_objects_internal (domain, method, NULL);
7726 * mono_method_body_get_object:
7727 * @domain: an app domain
7730 * Return an System.Reflection.MethodBody object representing the method @method.
7732 MonoReflectionMethodBody*
7733 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7736 MonoReflectionMethodBody *ret;
7737 MonoMethodHeader *header;
7739 MonoReflectionType *rt;
7740 guint32 method_rva, local_var_sig_token;
7742 unsigned char format, flags;
7745 /* for compatibility with .net */
7746 if (method_is_dynamic (method))
7747 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7749 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7751 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7752 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7753 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7754 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7755 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7758 image = method->klass->image;
7759 header = mono_method_get_header_checked (method, &error);
7760 mono_error_raise_exception (&error); /* FIXME don't raise here */
7762 if (!image_is_dynamic (image)) {
7763 /* Obtain local vars signature token */
7764 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7765 ptr = mono_image_rva_map (image, method_rva);
7766 flags = *(const unsigned char *) ptr;
7767 format = flags & METHOD_HEADER_FORMAT_MASK;
7769 case METHOD_HEADER_TINY_FORMAT:
7770 local_var_sig_token = 0;
7772 case METHOD_HEADER_FAT_FORMAT:
7776 local_var_sig_token = read32 (ptr);
7779 g_assert_not_reached ();
7782 local_var_sig_token = 0; //FIXME
7784 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7785 mono_error_raise_exception (&error); /* FIXME don't raise here */
7787 ret->init_locals = header->init_locals;
7788 ret->max_stack = header->max_stack;
7789 ret->local_var_sig_token = local_var_sig_token;
7790 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7791 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7794 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7795 for (i = 0; i < header->num_locals; ++i) {
7796 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7797 mono_error_raise_exception (&error); /* FIXME don't raise here */
7799 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7800 mono_error_raise_exception (&error); /* FIXME don't raise here */
7802 MONO_OBJECT_SETREF (info, local_type, rt);
7804 info->is_pinned = header->locals [i]->pinned;
7805 info->local_index = i;
7806 mono_array_setref (ret->locals, i, info);
7810 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7811 for (i = 0; i < header->num_clauses; ++i) {
7812 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7813 mono_error_raise_exception (&error); /* FIXME don't raise here */
7814 MonoExceptionClause *clause = &header->clauses [i];
7816 info->flags = clause->flags;
7817 info->try_offset = clause->try_offset;
7818 info->try_length = clause->try_len;
7819 info->handler_offset = clause->handler_offset;
7820 info->handler_length = clause->handler_len;
7821 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7822 info->filter_offset = clause->data.filter_offset;
7823 else if (clause->data.catch_class) {
7824 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7825 mono_error_raise_exception (&error); /* FIXME don't raise here */
7827 MONO_OBJECT_SETREF (info, catch_type, rt);
7830 mono_array_setref (ret->clauses, i, info);
7833 mono_metadata_free_mh (header);
7834 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7839 * mono_get_dbnull_object:
7840 * @domain: Domain where the object lives
7842 * Returns the System.DBNull.Value singleton object
7844 * Used as the value for ParameterInfo.DefaultValue
7847 mono_get_dbnull_object (MonoDomain *domain)
7850 static MonoClassField *dbnull_value_field = NULL;
7852 if (!dbnull_value_field) {
7853 MonoClass *dbnull_klass;
7854 dbnull_klass = mono_class_get_dbnull_class ();
7855 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7856 g_assert (dbnull_value_field);
7858 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7864 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7866 guint32 param_index, i, lastp, crow = 0;
7867 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7870 MonoClass *klass = method->klass;
7871 MonoImage *image = klass->image;
7872 MonoMethodSignature *methodsig = mono_method_signature (method);
7874 MonoTableInfo *constt;
7875 MonoTableInfo *methodt;
7876 MonoTableInfo *paramt;
7878 if (!methodsig->param_count)
7881 mono_class_init (klass);
7883 if (image_is_dynamic (klass->image)) {
7884 MonoReflectionMethodAux *aux;
7885 if (method->is_inflated)
7886 method = ((MonoMethodInflated*)method)->declaring;
7887 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7888 if (aux && aux->param_defaults) {
7889 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7890 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7895 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7896 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7897 constt = &image->tables [MONO_TABLE_CONSTANT];
7899 idx = mono_method_get_index (method) - 1;
7900 g_assert (idx != -1);
7902 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7903 if (idx + 1 < methodt->rows)
7904 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7906 lastp = paramt->rows + 1;
7908 for (i = param_index; i < lastp; ++i) {
7911 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7912 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7914 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7917 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7922 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7923 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7924 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7931 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7937 MonoType *basetype = type;
7942 klass = mono_class_from_mono_type (type);
7943 if (klass->valuetype) {
7944 object = mono_object_new_checked (domain, klass, &error);
7945 mono_error_raise_exception (&error); /* FIXME don't raise here */
7946 retval = ((gchar *) object + sizeof (MonoObject));
7947 if (klass->enumtype)
7948 basetype = mono_class_enum_basetype (klass);
7953 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7960 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7963 gboolean quoted = FALSE;
7965 memset (assembly, 0, sizeof (MonoAssemblyName));
7966 assembly->culture = "";
7967 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7974 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7985 /* Remove trailing whitespace */
7987 while (*s && g_ascii_isspace (*s))
7990 while (g_ascii_isspace (*p))
7993 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7995 assembly->major = strtoul (p, &s, 10);
7996 if (s == p || *s != '.')
7999 assembly->minor = strtoul (p, &s, 10);
8000 if (s == p || *s != '.')
8003 assembly->build = strtoul (p, &s, 10);
8004 if (s == p || *s != '.')
8007 assembly->revision = strtoul (p, &s, 10);
8011 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8013 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8014 assembly->culture = "";
8017 assembly->culture = p;
8018 while (*p && *p != ',') {
8022 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8024 if (strncmp (p, "null", 4) == 0) {
8029 while (*p && *p != ',') {
8032 len = (p - start + 1);
8033 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8034 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8035 g_strlcpy ((char*)assembly->public_key_token, start, len);
8038 while (*p && *p != ',')
8042 while (g_ascii_isspace (*p) || *p == ',') {
8056 * mono_reflection_parse_type:
8059 * Parse a type name as accepted by the GetType () method and output the info
8060 * extracted in the info structure.
8061 * the name param will be mangled, so, make a copy before passing it to this function.
8062 * The fields in info will be valid until the memory pointed to by name is valid.
8064 * See also mono_type_get_name () below.
8066 * Returns: 0 on parse error.
8069 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8070 MonoTypeNameParse *info)
8072 char *start, *p, *w, *last_point, *startn;
8073 int in_modifiers = 0;
8074 int isbyref = 0, rank = 0, isptr = 0;
8076 start = p = w = name;
8078 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8079 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8080 info->name = info->name_space = NULL;
8081 info->nested = NULL;
8082 info->modifiers = NULL;
8083 info->type_arguments = NULL;
8085 /* last_point separates the namespace from the name */
8088 while (*p == ' ') p++, start++, w++, name++;
8093 *p = 0; /* NULL terminate the name */
8095 info->nested = g_list_append (info->nested, startn);
8096 /* we have parsed the nesting namespace + name */
8100 info->name_space = start;
8102 info->name = last_point + 1;
8104 info->name_space = (char *)"";
8132 info->name_space = start;
8134 info->name = last_point + 1;
8136 info->name_space = (char *)"";
8143 if (isbyref) /* only one level allowed by the spec */
8147 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8151 if (isbyref) /* pointer to ref not okay */
8153 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8158 if (isbyref) /* array of ref and generic ref are not okay */
8160 //Decide if it's an array of a generic argument list
8165 if (*p == ',' || *p == '*' || *p == ']') { //array
8173 else if (*p == '*') /* '*' means unknown lower bound */
8174 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8181 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8183 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8186 info->type_arguments = g_ptr_array_new ();
8188 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8189 gboolean fqname = FALSE;
8191 g_ptr_array_add (info->type_arguments, subinfo);
8193 while (*p == ' ') p++;
8199 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8202 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8203 if (fqname && (*p != ']')) {
8211 while (*p && (*p != ']'))
8219 if (g_ascii_isspace (*aname)) {
8226 !assembly_name_to_aname (&subinfo->assembly, aname))
8228 } else if (fqname && (*p == ']')) {
8250 if (g_ascii_isspace (*p)) {
8257 return 0; /* missing assembly name */
8258 if (!assembly_name_to_aname (&info->assembly, p))
8264 if (info->assembly.name)
8267 // *w = 0; /* terminate class name */
8269 if (!info->name || !*info->name)
8273 /* add other consistency checks */
8279 * mono_identifier_unescape_type_name_chars:
8280 * @identifier: the display name of a mono type
8283 * The name in internal form, that is without escaping backslashes.
8285 * The string is modified in place!
8288 mono_identifier_unescape_type_name_chars(char* identifier)
8293 for (w = r = identifier; *r != 0; r++)
8311 mono_identifier_unescape_info (MonoTypeNameParse* info);
8314 unescape_each_type_argument(void* data, void* user_data)
8316 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8317 mono_identifier_unescape_info (info);
8321 unescape_each_nested_name (void* data, void* user_data)
8323 char* nested_name = (char*) data;
8324 mono_identifier_unescape_type_name_chars(nested_name);
8328 * mono_identifier_unescape_info:
8330 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8334 * Destructively updates the info by unescaping the identifiers that
8335 * comprise the type namespace, name, nested types (if any) and
8336 * generic type arguments (if any).
8338 * The resulting info has the names in internal form.
8342 mono_identifier_unescape_info (MonoTypeNameParse *info)
8346 mono_identifier_unescape_type_name_chars(info->name_space);
8347 mono_identifier_unescape_type_name_chars(info->name);
8348 // but don't escape info->assembly
8349 if (info->type_arguments)
8350 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8352 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8356 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8358 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8360 mono_identifier_unescape_info (info);
8366 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8368 gboolean type_resolve = FALSE;
8370 MonoImage *rootimage = image;
8372 if (info->assembly.name) {
8373 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8374 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8376 * This could happen in the AOT compiler case when the search hook is not
8379 assembly = image->assembly;
8381 /* then we must load the assembly ourselve - see #60439 */
8382 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8386 image = assembly->image;
8387 } else if (!image) {
8388 image = mono_defaults.corlib;
8391 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8392 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8393 image = mono_defaults.corlib;
8394 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8401 * mono_reflection_get_type_internal:
8403 * Returns: may return NULL on success, sets error on failure.
8406 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8411 gboolean bounded = FALSE;
8413 mono_error_init (error);
8415 image = mono_defaults.corlib;
8418 rootimage = mono_defaults.corlib;
8421 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8423 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8428 for (mod = info->nested; mod; mod = mod->next) {
8429 gpointer iter = NULL;
8433 mono_class_init (parent);
8435 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8437 char *nested_name, *nested_nspace;
8438 gboolean match = TRUE;
8440 lastp = strrchr ((const char *)mod->data, '.');
8442 /* Nested classes can have namespaces */
8445 nested_name = g_strdup (lastp + 1);
8446 nspace_len = lastp - (char*)mod->data;
8447 nested_nspace = (char *)g_malloc (nspace_len + 1);
8448 memcpy (nested_nspace, mod->data, nspace_len);
8449 nested_nspace [nspace_len] = '\0';
8452 nested_name = (char *)mod->data;
8453 nested_nspace = NULL;
8456 if (nested_nspace) {
8458 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8461 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8467 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8470 if (strcmp (klass->name, nested_name) != 0)
8475 g_free (nested_name);
8476 g_free (nested_nspace);
8488 if (info->type_arguments) {
8489 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8490 MonoReflectionType *the_type;
8494 for (i = 0; i < info->type_arguments->len; i++) {
8495 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8497 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8498 if (!type_args [i]) {
8504 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8508 instance = mono_reflection_bind_generic_parameters (
8509 the_type, info->type_arguments->len, type_args);
8515 klass = mono_class_from_mono_type (instance);
8518 for (mod = info->modifiers; mod; mod = mod->next) {
8519 modval = GPOINTER_TO_UINT (mod->data);
8520 if (!modval) { /* byref: must be last modifier */
8521 return &klass->this_arg;
8522 } else if (modval == -1) {
8523 klass = mono_ptr_class_get (&klass->byval_arg);
8524 } else if (modval == -2) {
8526 } else { /* array rank */
8527 klass = mono_bounded_array_class_get (klass, modval, bounded);
8531 return &klass->byval_arg;
8535 * mono_reflection_get_type:
8536 * @image: a metadata context
8537 * @info: type description structure
8538 * @ignorecase: flag for case-insensitive string compares
8539 * @type_resolve: whenever type resolve was already tried
8541 * Build a MonoType from the type description in @info.
8546 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8547 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8551 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8553 MonoReflectionAssemblyBuilder *abuilder;
8557 mono_error_init (error);
8558 g_assert (assembly_is_dynamic (assembly));
8559 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8563 /* Enumerate all modules */
8566 if (abuilder->modules) {
8567 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8568 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8569 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8572 if (!mono_error_ok (error))
8577 if (!type && abuilder->loaded_modules) {
8578 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8579 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8580 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8583 if (!mono_error_ok (error))
8592 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8596 MonoReflectionAssembly *assembly;
8600 if (image && image_is_dynamic (image))
8601 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8603 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8605 if (!mono_error_ok (&error))
8606 mono_error_raise_exception (&error); /* FIXME don't raise here */
8610 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8617 *type_resolve = TRUE;
8620 /* Reconstruct the type name */
8621 fullName = g_string_new ("");
8622 if (info->name_space && (info->name_space [0] != '\0'))
8623 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8625 g_string_printf (fullName, "%s", info->name);
8626 for (mod = info->nested; mod; mod = mod->next)
8627 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8629 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8630 mono_error_raise_exception (&error); /* FIXME don't raise here */
8633 if (assembly_is_dynamic (assembly->assembly))
8634 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8635 info, ignorecase, &error);
8637 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8638 info, ignorecase, &error);
8640 g_string_free (fullName, TRUE);
8641 if (!mono_error_ok (&error))
8642 mono_error_raise_exception (&error); /* FIXME don't raise here */
8647 mono_reflection_free_type_info (MonoTypeNameParse *info)
8649 g_list_free (info->modifiers);
8650 g_list_free (info->nested);
8652 if (info->type_arguments) {
8655 for (i = 0; i < info->type_arguments->len; i++) {
8656 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8658 mono_reflection_free_type_info (subinfo);
8659 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8663 g_ptr_array_free (info->type_arguments, TRUE);
8668 * mono_reflection_type_from_name:
8670 * @image: a metadata context (can be NULL).
8672 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8673 * it defaults to get the type from @image or, if @image is NULL or loading
8674 * from it fails, uses corlib.
8678 mono_reflection_type_from_name (char *name, MonoImage *image)
8680 MonoType *type = NULL;
8681 MonoTypeNameParse info;
8684 /* Make a copy since parse_type modifies its argument */
8685 tmp = g_strdup (name);
8687 /*g_print ("requested type %s\n", str);*/
8688 if (mono_reflection_parse_type (tmp, &info)) {
8689 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8693 mono_reflection_free_type_info (&info);
8698 * mono_reflection_get_token:
8700 * Return the metadata token of OBJ which should be an object
8701 * representing a metadata element.
8704 mono_reflection_get_token (MonoObject *obj)
8710 klass = obj->vtable->klass;
8712 if (strcmp (klass->name, "MethodBuilder") == 0) {
8713 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8715 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8716 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8717 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8719 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8720 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8721 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8723 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8724 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8725 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8726 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8727 } else if (strcmp (klass->name, "MonoType") == 0) {
8728 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8729 mono_error_raise_exception (&error); /* FIXME don't raise here */
8730 MonoClass *mc = mono_class_from_mono_type (type);
8731 if (!mono_class_init (mc))
8732 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8734 token = mc->type_token;
8735 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8736 strcmp (klass->name, "MonoMethod") == 0 ||
8737 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8738 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8739 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8740 if (m->method->is_inflated) {
8741 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8742 return inflated->declaring->token;
8744 token = m->method->token;
8746 } else if (strcmp (klass->name, "MonoField") == 0) {
8747 MonoReflectionField *f = (MonoReflectionField*)obj;
8749 if (is_field_on_inst (f->field)) {
8750 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8752 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8753 int field_index = f->field - dgclass->fields;
8756 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8757 obj = dgclass->field_objects [field_index];
8758 return mono_reflection_get_token (obj);
8761 token = mono_class_get_field_token (f->field);
8762 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8763 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8765 token = mono_class_get_property_token (p->property);
8766 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8767 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8769 token = mono_class_get_event_token (p->event);
8770 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8771 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8772 MonoClass *member_class = mono_object_class (p->MemberImpl);
8773 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8775 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8776 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8777 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8780 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8781 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8783 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8784 MonoException *ex = mono_get_exception_not_implemented (msg);
8786 mono_raise_exception (ex);
8793 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8797 int slen = mono_metadata_decode_value (p, &p);
8799 mono_error_init (error);
8801 n = (char *)g_memdup (p, slen + 1);
8803 t = mono_reflection_type_from_name (n, image);
8805 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8806 /* We don't free n, it's consumed by mono_error */
8807 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8813 return mono_class_from_mono_type (t);
8817 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8819 int slen, type = t->type;
8820 MonoClass *tklass = t->data.klass;
8822 mono_error_init (error);
8828 case MONO_TYPE_BOOLEAN: {
8829 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8834 case MONO_TYPE_CHAR:
8836 case MONO_TYPE_I2: {
8837 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8842 #if SIZEOF_VOID_P == 4
8848 case MONO_TYPE_I4: {
8849 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8854 #if SIZEOF_VOID_P == 8
8855 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8859 case MONO_TYPE_I8: {
8860 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8865 case MONO_TYPE_R8: {
8866 double *val = (double *)g_malloc (sizeof (double));
8871 case MONO_TYPE_VALUETYPE:
8872 if (t->data.klass->enumtype) {
8873 type = mono_class_enum_basetype (t->data.klass)->type;
8876 MonoClass *k = t->data.klass;
8878 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8879 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8885 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8888 case MONO_TYPE_STRING:
8889 if (*p == (char)0xFF) {
8893 slen = mono_metadata_decode_value (p, &p);
8895 return mono_string_new_len (mono_domain_get (), p, slen);
8896 case MONO_TYPE_CLASS: {
8897 MonoReflectionType *rt;
8900 if (*p == (char)0xFF) {
8905 slen = mono_metadata_decode_value (p, &p);
8906 n = (char *)g_memdup (p, slen + 1);
8908 t = mono_reflection_type_from_name (n, image);
8910 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8911 /* We don't free n, it's consumed by mono_error */
8912 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8918 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8919 if (!mono_error_ok (error))
8924 case MONO_TYPE_OBJECT: {
8927 MonoClass *subc = NULL;
8932 } else if (subt == 0x0E) {
8933 type = MONO_TYPE_STRING;
8935 } else if (subt == 0x1D) {
8936 MonoType simple_type = {{0}};
8940 type = MONO_TYPE_SZARRAY;
8941 if (etype == 0x50) {
8942 tklass = mono_defaults.systemtype_class;
8943 } else if (etype == 0x55) {
8944 tklass = load_cattr_enum_type (image, p, &p, error);
8945 if (!mono_error_ok (error))
8949 /* See Partition II, Appendix B3 */
8950 etype = MONO_TYPE_OBJECT;
8951 simple_type.type = (MonoTypeEnum)etype;
8952 tklass = mono_class_from_mono_type (&simple_type);
8955 } else if (subt == 0x55) {
8958 slen = mono_metadata_decode_value (p, &p);
8959 n = (char *)g_memdup (p, slen + 1);
8961 t = mono_reflection_type_from_name (n, image);
8963 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8964 /* We don't free n, it's consumed by mono_error */
8965 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8970 subc = mono_class_from_mono_type (t);
8971 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8972 MonoType simple_type = {{0}};
8973 simple_type.type = (MonoTypeEnum)subt;
8974 subc = mono_class_from_mono_type (&simple_type);
8976 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8978 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8980 if (mono_error_ok (error)) {
8981 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8982 g_assert (!subc->has_references);
8983 if (mono_error_ok (error))
8984 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8990 case MONO_TYPE_SZARRAY: {
8992 guint32 i, alen, basetype;
8995 if (alen == 0xffffffff) {
8999 arr = mono_array_new (mono_domain_get(), tklass, alen);
9000 basetype = tklass->byval_arg.type;
9001 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9002 basetype = mono_class_enum_basetype (tklass)->type;
9007 case MONO_TYPE_BOOLEAN:
9008 for (i = 0; i < alen; i++) {
9009 MonoBoolean val = *p++;
9010 mono_array_set (arr, MonoBoolean, i, val);
9013 case MONO_TYPE_CHAR:
9016 for (i = 0; i < alen; i++) {
9017 guint16 val = read16 (p);
9018 mono_array_set (arr, guint16, i, val);
9025 for (i = 0; i < alen; i++) {
9026 guint32 val = read32 (p);
9027 mono_array_set (arr, guint32, i, val);
9032 for (i = 0; i < alen; i++) {
9035 mono_array_set (arr, double, i, val);
9041 for (i = 0; i < alen; i++) {
9042 guint64 val = read64 (p);
9043 mono_array_set (arr, guint64, i, val);
9047 case MONO_TYPE_CLASS:
9048 case MONO_TYPE_OBJECT:
9049 case MONO_TYPE_STRING:
9050 case MONO_TYPE_SZARRAY:
9051 for (i = 0; i < alen; i++) {
9052 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9053 if (!mono_error_ok (error))
9055 mono_array_setref (arr, i, item);
9059 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9065 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9071 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9073 static MonoMethod *ctor;
9075 void *params [2], *unboxed;
9077 mono_error_init (error);
9080 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9082 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9083 return_val_if_nok (error, NULL);
9086 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9087 return_val_if_nok (error, NULL);
9088 unboxed = mono_object_unbox (retval);
9090 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9091 return_val_if_nok (error, NULL);
9097 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9099 static MonoMethod *ctor;
9101 void *unboxed, *params [2];
9103 mono_error_init (error);
9106 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9109 params [1] = typedarg;
9110 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9111 return_val_if_nok (error, NULL);
9113 unboxed = mono_object_unbox (retval);
9115 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9116 return_val_if_nok (error, NULL);
9122 type_is_reference (MonoType *type)
9124 switch (type->type) {
9125 case MONO_TYPE_BOOLEAN:
9126 case MONO_TYPE_CHAR:
9139 case MONO_TYPE_VALUETYPE:
9147 free_param_data (MonoMethodSignature *sig, void **params) {
9149 for (i = 0; i < sig->param_count; ++i) {
9150 if (!type_is_reference (sig->params [i]))
9151 g_free (params [i]);
9156 * Find the field index in the metadata FieldDef table.
9159 find_field_index (MonoClass *klass, MonoClassField *field) {
9162 for (i = 0; i < klass->field.count; ++i) {
9163 if (field == &klass->fields [i])
9164 return klass->field.first + 1 + i;
9170 * Find the property index in the metadata Property table.
9173 find_property_index (MonoClass *klass, MonoProperty *property) {
9176 for (i = 0; i < klass->ext->property.count; ++i) {
9177 if (property == &klass->ext->properties [i])
9178 return klass->ext->property.first + 1 + i;
9184 * Find the event index in the metadata Event table.
9187 find_event_index (MonoClass *klass, MonoEvent *event) {
9190 for (i = 0; i < klass->ext->event.count; ++i) {
9191 if (event == &klass->ext->events [i])
9192 return klass->ext->event.first + 1 + i;
9198 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9200 const char *p = (const char*)data;
9202 guint32 i, j, num_named;
9204 void *params_buf [32];
9205 void **params = NULL;
9206 MonoMethodSignature *sig;
9207 MonoObject *exc = NULL;
9209 mono_error_init (error);
9211 mono_class_init (method->klass);
9213 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9214 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9219 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9220 if (!mono_error_ok (error)) return NULL;
9222 mono_runtime_invoke_checked (method, attr, NULL, error);
9223 if (!mono_error_ok (error))
9229 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9232 /*g_print ("got attr %s\n", method->klass->name);*/
9234 sig = mono_method_signature (method);
9235 if (sig->param_count < 32) {
9236 params = params_buf;
9237 memset (params, 0, sizeof (void*) * sig->param_count);
9239 /* Allocate using GC so it gets GC tracking */
9240 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9245 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9246 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9247 if (!mono_error_ok (error))
9252 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9253 if (!mono_error_ok (error)) goto fail;
9255 mono_runtime_try_invoke (method, attr, params, &exc, error);
9256 if (!mono_error_ok (error))
9261 num_named = read16 (named);
9263 for (j = 0; j < num_named; j++) {
9265 char *name, named_type, data_type;
9266 named_type = *named++;
9267 data_type = *named++; /* type of data */
9268 if (data_type == MONO_TYPE_SZARRAY)
9269 data_type = *named++;
9270 if (data_type == MONO_TYPE_ENUM) {
9273 type_len = mono_metadata_decode_blob_size (named, &named);
9274 type_name = (char *)g_malloc (type_len + 1);
9275 memcpy (type_name, named, type_len);
9276 type_name [type_len] = 0;
9278 /* FIXME: lookup the type and check type consistency */
9281 name_len = mono_metadata_decode_blob_size (named, &named);
9282 name = (char *)g_malloc (name_len + 1);
9283 memcpy (name, named, name_len);
9284 name [name_len] = 0;
9286 if (named_type == 0x53) {
9287 MonoClassField *field;
9290 /* how this fail is a blackbox */
9291 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9293 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9298 val = load_cattr_value (image, field->type, named, &named, error);
9299 if (!mono_error_ok (error)) {
9301 if (!type_is_reference (field->type))
9306 mono_field_set_value (attr, field, val);
9307 if (!type_is_reference (field->type))
9309 } else if (named_type == 0x54) {
9312 MonoType *prop_type;
9314 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9317 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9323 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9328 /* can we have more that 1 arg in a custom attr named property? */
9329 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9330 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9332 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9333 if (!mono_error_ok (error)) {
9335 if (!type_is_reference (prop_type))
9336 g_free (pparams [0]);
9341 mono_property_set_value (prop, attr, pparams, NULL);
9342 if (!type_is_reference (prop_type))
9343 g_free (pparams [0]);
9348 free_param_data (method->signature, params);
9349 if (params != params_buf)
9350 mono_gc_free_fixed (params);
9355 free_param_data (method->signature, params);
9356 if (params != params_buf)
9357 mono_gc_free_fixed (params);
9359 mono_raise_exception ((MonoException*)exc);
9364 * mono_reflection_create_custom_attr_data_args:
9366 * Create an array of typed and named arguments from the cattr blob given by DATA.
9367 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9368 * NAMED_ARG_INFO will contain information about the named arguments.
9371 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)
9373 MonoArray *typedargs, *namedargs;
9374 MonoClass *attrklass;
9376 const char *p = (const char*)data;
9378 guint32 i, j, num_named;
9379 CattrNamedArg *arginfo = NULL;
9383 *named_arg_info = NULL;
9385 mono_error_init (error);
9387 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9388 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9392 mono_class_init (method->klass);
9394 domain = mono_domain_get ();
9396 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9399 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9403 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9407 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9408 if (!mono_error_ok (error)) {
9409 if (!type_is_reference (mono_method_signature (method)->params [i]))
9414 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9415 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9416 mono_array_setref (typedargs, i, obj);
9418 if (!type_is_reference (mono_method_signature (method)->params [i]))
9423 num_named = read16 (named);
9424 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9426 attrklass = method->klass;
9428 arginfo = g_new0 (CattrNamedArg, num_named);
9429 *named_arg_info = arginfo;
9431 for (j = 0; j < num_named; j++) {
9433 char *name, named_type, data_type;
9434 named_type = *named++;
9435 data_type = *named++; /* type of data */
9436 if (data_type == MONO_TYPE_SZARRAY)
9437 data_type = *named++;
9438 if (data_type == MONO_TYPE_ENUM) {
9441 type_len = mono_metadata_decode_blob_size (named, &named);
9442 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9445 type_name = (char *)g_malloc (type_len + 1);
9446 memcpy (type_name, named, type_len);
9447 type_name [type_len] = 0;
9449 /* FIXME: lookup the type and check type consistency */
9452 name_len = mono_metadata_decode_blob_size (named, &named);
9453 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9455 name = (char *)g_malloc (name_len + 1);
9456 memcpy (name, named, name_len);
9457 name [name_len] = 0;
9459 if (named_type == 0x53) {
9461 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9469 arginfo [j].type = field->type;
9470 arginfo [j].field = field;
9472 val = load_cattr_value (image, field->type, named, &named, error);
9473 if (!mono_error_ok (error)) {
9474 if (!type_is_reference (field->type))
9480 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9481 mono_array_setref (namedargs, j, obj);
9482 if (!type_is_reference (field->type))
9484 } else if (named_type == 0x54) {
9486 MonoType *prop_type;
9487 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9490 if (!prop || !prop->set) {
9495 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9496 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9498 arginfo [j].type = prop_type;
9499 arginfo [j].prop = prop;
9501 val = load_cattr_value (image, prop_type, named, &named, error);
9502 if (!mono_error_ok (error)) {
9503 if (!type_is_reference (prop_type))
9509 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9510 mono_array_setref (namedargs, j, obj);
9511 if (!type_is_reference (prop_type))
9517 *typed_args = typedargs;
9518 *named_args = namedargs;
9521 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9523 *named_arg_info = NULL;
9527 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9530 MonoArray *typedargs, *namedargs;
9533 CattrNamedArg *arginfo = NULL;
9537 mono_error_init (&error);
9545 image = assembly->assembly->image;
9546 method = ref_method->method;
9547 domain = mono_object_domain (ref_method);
9549 if (!mono_class_init (method->klass))
9550 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9552 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9553 if (!mono_error_ok (&error))
9556 if (mono_loader_get_last_error ()) {
9557 mono_error_set_from_loader_error (&error);
9561 if (!typedargs || !namedargs)
9564 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9565 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9566 MonoObject *typedarg;
9568 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9569 if (!is_ok (&error))
9571 mono_array_setref (typedargs, i, typedarg);
9574 for (i = 0; i < mono_array_length (namedargs); ++i) {
9575 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9576 MonoObject *typedarg, *namedarg, *minfo;
9578 if (arginfo [i].prop) {
9579 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9583 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9584 if (!mono_error_ok (&error))
9588 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9589 if (!is_ok (&error))
9591 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9592 if (!is_ok (&error))
9595 mono_array_setref (namedargs, i, namedarg);
9598 *ctor_args = typedargs;
9599 *named_args = namedargs;
9602 mono_error_raise_exception (&error);
9607 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9609 static MonoMethod *ctor;
9615 mono_error_init (error);
9617 g_assert (image->assembly);
9620 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9622 domain = mono_domain_get ();
9623 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9624 return_val_if_nok (error, NULL);
9625 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9626 return_val_if_nok (error, NULL);
9627 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9628 return_val_if_nok (error, NULL);
9629 params [2] = (gpointer)&cattr->data;
9630 params [3] = &cattr->data_size;
9632 mono_runtime_invoke_checked (ctor, attr, params, error);
9633 return_val_if_nok (error, NULL);
9638 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9644 mono_error_init (error);
9647 for (i = 0; i < cinfo->num_attrs; ++i) {
9648 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9652 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9654 for (i = 0; i < cinfo->num_attrs; ++i) {
9655 if (!cinfo->attrs [i].ctor) {
9656 /* The cattr type is not finished yet */
9657 /* We should include the type name but cinfo doesn't contain it */
9658 mono_error_set_type_load_name (error, NULL, NULL, "");
9661 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9662 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9663 if (!mono_error_ok (error))
9665 mono_array_setref (result, n, attr);
9673 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9676 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9677 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9683 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9689 mono_error_init (error);
9690 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9691 for (i = 0; i < cinfo->num_attrs; ++i) {
9692 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9693 return_val_if_nok (error, NULL);
9694 mono_array_setref (result, i, attr);
9700 * mono_custom_attrs_from_index:
9702 * Returns: NULL if no attributes are found or if a loading error occurs.
9705 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9708 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9709 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9713 * mono_custom_attrs_from_index_checked:
9715 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9718 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9720 guint32 mtoken, i, len;
9721 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9723 MonoCustomAttrInfo *ainfo;
9724 GList *tmp, *list = NULL;
9726 MonoCustomAttrEntry* attr;
9728 mono_error_init (error);
9730 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9732 i = mono_metadata_custom_attrs_from_index (image, idx);
9736 while (i < ca->rows) {
9737 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9739 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9742 len = g_list_length (list);
9745 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9746 ainfo->num_attrs = len;
9747 ainfo->image = image;
9748 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9749 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9750 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9751 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9752 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9753 mtoken |= MONO_TOKEN_METHOD_DEF;
9755 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9756 mtoken |= MONO_TOKEN_MEMBER_REF;
9759 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9762 attr = &ainfo->attrs [i - 1];
9763 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9765 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9771 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9772 /*FIXME raising an exception here doesn't make any sense*/
9773 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9778 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9779 attr->data_size = mono_metadata_decode_value (data, &data);
9780 attr->data = (guchar*)data;
9788 mono_custom_attrs_from_method (MonoMethod *method)
9791 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9792 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9797 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9801 mono_error_init (error);
9804 * An instantiated method has the same cattrs as the generic method definition.
9806 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9807 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9809 if (method->is_inflated)
9810 method = ((MonoMethodInflated *) method)->declaring;
9812 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9813 return lookup_custom_attr (method->klass->image, method);
9816 /* Synthetic methods */
9819 idx = mono_method_get_index (method);
9820 idx <<= MONO_CUSTOM_ATTR_BITS;
9821 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9822 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9826 mono_custom_attrs_from_class (MonoClass *klass)
9829 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9830 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9835 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9839 mono_error_init (error);
9841 if (klass->generic_class)
9842 klass = klass->generic_class->container_class;
9844 if (image_is_dynamic (klass->image))
9845 return lookup_custom_attr (klass->image, klass);
9847 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9848 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9849 idx <<= MONO_CUSTOM_ATTR_BITS;
9850 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9852 idx = mono_metadata_token_index (klass->type_token);
9853 idx <<= MONO_CUSTOM_ATTR_BITS;
9854 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9856 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9860 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9863 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9864 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9869 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9873 mono_error_init (error);
9875 if (image_is_dynamic (assembly->image))
9876 return lookup_custom_attr (assembly->image, assembly);
9877 idx = 1; /* there is only one assembly */
9878 idx <<= MONO_CUSTOM_ATTR_BITS;
9879 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9880 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9883 static MonoCustomAttrInfo*
9884 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9888 if (image_is_dynamic (image))
9889 return lookup_custom_attr (image, image);
9890 idx = 1; /* there is only one module */
9891 idx <<= MONO_CUSTOM_ATTR_BITS;
9892 idx |= MONO_CUSTOM_ATTR_MODULE;
9893 return mono_custom_attrs_from_index_checked (image, idx, error);
9897 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9900 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9901 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9906 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9910 if (image_is_dynamic (klass->image)) {
9911 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9912 return lookup_custom_attr (klass->image, property);
9914 idx = find_property_index (klass, property);
9915 idx <<= MONO_CUSTOM_ATTR_BITS;
9916 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9917 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9921 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9924 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9925 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9930 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9934 if (image_is_dynamic (klass->image)) {
9935 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9936 return lookup_custom_attr (klass->image, event);
9938 idx = find_event_index (klass, event);
9939 idx <<= MONO_CUSTOM_ATTR_BITS;
9940 idx |= MONO_CUSTOM_ATTR_EVENT;
9941 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9945 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9948 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9949 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9954 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9957 mono_error_init (error);
9959 if (image_is_dynamic (klass->image)) {
9960 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9961 return lookup_custom_attr (klass->image, field);
9963 idx = find_field_index (klass, field);
9964 idx <<= MONO_CUSTOM_ATTR_BITS;
9965 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9966 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9970 * mono_custom_attrs_from_param:
9971 * @method: handle to the method that we want to retrieve custom parameter information from
9972 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9974 * The result must be released with mono_custom_attrs_free().
9976 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9979 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9982 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9983 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9988 * mono_custom_attrs_from_param_checked:
9989 * @method: handle to the method that we want to retrieve custom parameter information from
9990 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9991 * @error: set on error
9993 * The result must be released with mono_custom_attrs_free().
9995 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9998 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10001 guint32 i, idx, method_index;
10002 guint32 param_list, param_last, param_pos, found;
10004 MonoReflectionMethodAux *aux;
10006 mono_error_init (error);
10009 * An instantiated method has the same cattrs as the generic method definition.
10011 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10012 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10014 if (method->is_inflated)
10015 method = ((MonoMethodInflated *) method)->declaring;
10017 if (image_is_dynamic (method->klass->image)) {
10018 MonoCustomAttrInfo *res, *ainfo;
10021 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10022 if (!aux || !aux->param_cattr)
10025 /* Need to copy since it will be freed later */
10026 ainfo = aux->param_cattr [param];
10029 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10030 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10031 memcpy (res, ainfo, size);
10035 image = method->klass->image;
10036 method_index = mono_method_get_index (method);
10039 ca = &image->tables [MONO_TABLE_METHOD];
10041 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10042 if (method_index == ca->rows) {
10043 ca = &image->tables [MONO_TABLE_PARAM];
10044 param_last = ca->rows + 1;
10046 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10047 ca = &image->tables [MONO_TABLE_PARAM];
10050 for (i = param_list; i < param_last; ++i) {
10051 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10052 if (param_pos == param) {
10060 idx <<= MONO_CUSTOM_ATTR_BITS;
10061 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10062 return mono_custom_attrs_from_index_checked (image, idx, error);
10066 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10070 for (i = 0; i < ainfo->num_attrs; ++i) {
10071 klass = ainfo->attrs [i].ctor->klass;
10072 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10079 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10082 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10083 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10088 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10094 mono_error_init (error);
10097 for (i = 0; i < ainfo->num_attrs; ++i) {
10098 klass = ainfo->attrs [i].ctor->klass;
10099 if (mono_class_has_parent (klass, attr_klass)) {
10104 if (attr_index == -1)
10107 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10108 if (!mono_error_ok (error))
10110 return mono_array_get (attrs, MonoObject*, attr_index);
10114 * mono_reflection_get_custom_attrs_info:
10115 * @obj: a reflection object handle
10117 * Return the custom attribute info for attributes defined for the
10118 * reflection handle @obj. The objects.
10120 * FIXME this function leaks like a sieve for SRE objects.
10122 MonoCustomAttrInfo*
10123 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10126 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10127 mono_error_assert_ok (&error);
10132 * mono_reflection_get_custom_attrs_info_checked:
10133 * @obj: a reflection object handle
10134 * @error: set on error
10136 * Return the custom attribute info for attributes defined for the
10137 * reflection handle @obj. The objects.
10139 * On failure returns NULL and sets @error.
10141 * FIXME this function leaks like a sieve for SRE objects.
10143 MonoCustomAttrInfo*
10144 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10147 MonoCustomAttrInfo *cinfo = NULL;
10149 mono_error_init (error);
10151 klass = obj->vtable->klass;
10152 if (klass == mono_defaults.monotype_class) {
10153 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10154 return_val_if_nok (error, NULL);
10155 klass = mono_class_from_mono_type (type);
10156 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10157 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10158 return_val_if_nok (error, NULL);
10159 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10160 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10161 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10162 return_val_if_nok (error, NULL);
10163 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10164 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10165 cinfo = mono_custom_attrs_from_module (module->image, error);
10166 return_val_if_nok (error, NULL);
10167 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10168 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10169 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10170 return_val_if_nok (error, NULL);
10171 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10172 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10173 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10174 return_val_if_nok (error, NULL);
10175 } else if (strcmp ("MonoField", klass->name) == 0) {
10176 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10177 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10178 return_val_if_nok (error, NULL);
10179 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10180 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10181 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10182 return_val_if_nok (error, NULL);
10183 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10184 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10185 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10186 return_val_if_nok (error, NULL);
10187 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10188 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10189 MonoClass *member_class = mono_object_class (param->MemberImpl);
10190 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10191 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10192 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10193 return_val_if_nok (error, NULL);
10194 } else if (is_sr_mono_property (member_class)) {
10195 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10196 MonoMethod *method;
10197 if (!(method = prop->property->get))
10198 method = prop->property->set;
10201 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10202 return_val_if_nok (error, NULL);
10204 #ifndef DISABLE_REFLECTION_EMIT
10205 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10206 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10207 return_val_if_nok (error, NULL);
10208 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10209 return_val_if_nok (error, NULL);
10210 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10211 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10212 MonoMethod *method = NULL;
10213 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10214 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10215 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10216 method = ((MonoReflectionMethod *)c->cb)->method;
10218 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));
10220 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10221 return_val_if_nok (error, NULL);
10225 char *type_name = mono_type_get_full_name (member_class);
10226 mono_error_set_generic_error (error, "System", "NotSupportedException",
10227 "Custom attributes on a ParamInfo with member %s are not supported",
10229 g_free (type_name);
10232 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10233 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10234 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10235 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10236 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10237 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10238 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10239 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10240 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10241 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10242 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10243 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10244 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10245 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10246 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10247 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10248 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10249 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10250 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10251 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10252 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10253 return_val_if_nok (error, NULL);
10254 } else { /* handle other types here... */
10255 g_error ("get custom attrs not yet supported for %s", klass->name);
10262 * mono_reflection_get_custom_attrs_by_type:
10263 * @obj: a reflection object handle
10265 * Return an array with all the custom attributes defined of the
10266 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10267 * of that type are returned. The objects are fully build. Return NULL if a loading error
10271 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10274 MonoCustomAttrInfo *cinfo;
10276 mono_error_init (error);
10278 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10279 return_val_if_nok (error, NULL);
10281 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10284 if (!cinfo->cached)
10285 mono_custom_attrs_free (cinfo);
10287 mono_loader_assert_no_error ();
10288 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10295 * mono_reflection_get_custom_attrs:
10296 * @obj: a reflection object handle
10298 * Return an array with all the custom attributes defined of the
10299 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10303 mono_reflection_get_custom_attrs (MonoObject *obj)
10307 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10311 * mono_reflection_get_custom_attrs_data:
10312 * @obj: a reflection obj handle
10314 * Returns an array of System.Reflection.CustomAttributeData,
10315 * which include information about attributes reflected on
10316 * types loaded using the Reflection Only methods
10319 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10323 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10324 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10329 * mono_reflection_get_custom_attrs_data_checked:
10330 * @obj: a reflection obj handle
10331 * @error: set on error
10333 * Returns an array of System.Reflection.CustomAttributeData,
10334 * which include information about attributes reflected on
10335 * types loaded using the Reflection Only methods
10338 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10341 MonoCustomAttrInfo *cinfo;
10343 mono_error_init (error);
10345 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10346 return_val_if_nok (error, NULL);
10348 result = mono_custom_attrs_data_construct (cinfo, error);
10349 return_val_if_nok (error, NULL);
10350 if (!cinfo->cached)
10351 mono_custom_attrs_free (cinfo);
10353 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10355 if (mono_loader_get_last_error ())
10356 mono_error_set_from_loader_error (error);
10361 static MonoReflectionType*
10362 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10364 static MonoMethod *method_get_underlying_system_type = NULL;
10365 MonoReflectionType *rt;
10366 MonoMethod *usertype_method;
10368 mono_error_init (error);
10370 if (!method_get_underlying_system_type)
10371 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10373 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10375 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10382 is_corlib_type (MonoClass *klass)
10384 return klass->image == mono_defaults.corlib;
10387 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10388 static MonoClass *cached_class; \
10389 if (cached_class) \
10390 return cached_class == _class; \
10391 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10392 cached_class = _class; \
10399 #ifndef DISABLE_REFLECTION_EMIT
10401 is_sre_array (MonoClass *klass)
10403 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10407 is_sre_byref (MonoClass *klass)
10409 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10413 is_sre_pointer (MonoClass *klass)
10415 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10419 is_sre_generic_instance (MonoClass *klass)
10421 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10425 is_sre_type_builder (MonoClass *klass)
10427 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10431 is_sre_method_builder (MonoClass *klass)
10433 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10437 is_sre_ctor_builder (MonoClass *klass)
10439 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10443 is_sre_field_builder (MonoClass *klass)
10445 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10449 is_sre_method_on_tb_inst (MonoClass *klass)
10451 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10455 is_sre_ctor_on_tb_inst (MonoClass *klass)
10457 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10461 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10464 mono_error_init (error);
10471 if (is_usertype (ref)) {
10472 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10473 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10479 klass = mono_object_class (ref);
10481 if (is_sre_array (klass)) {
10483 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10484 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10485 return_val_if_nok (error, NULL);
10487 if (sre_array->rank == 0) //single dimentional array
10488 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10490 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10491 sre_array->type.type = res;
10493 } else if (is_sre_byref (klass)) {
10495 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10496 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10497 return_val_if_nok (error, NULL);
10499 res = &mono_class_from_mono_type (base)->this_arg;
10500 sre_byref->type.type = res;
10502 } else if (is_sre_pointer (klass)) {
10504 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10505 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10506 return_val_if_nok (error, NULL);
10508 res = &mono_ptr_class_get (base)->byval_arg;
10509 sre_pointer->type.type = res;
10511 } else if (is_sre_generic_instance (klass)) {
10512 MonoType *res, **types;
10513 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10516 count = mono_array_length (gclass->type_arguments);
10517 types = g_new0 (MonoType*, count);
10518 for (i = 0; i < count; ++i) {
10519 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10520 types [i] = mono_reflection_type_get_handle (t, error);
10521 if (!types[i] || !is_ok (error)) {
10527 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10530 gclass->type.type = res;
10534 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10539 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10542 mono_reflection_type_get_handle (type, &error);
10543 mono_error_set_pending_exception (&error);
10547 mono_reflection_register_with_runtime (MonoReflectionType *type)
10550 MonoType *res = mono_reflection_type_get_handle (type, &error);
10551 mono_error_raise_exception (&error); /* FIXME don't raise here */
10552 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10556 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10558 klass = mono_class_from_mono_type (res);
10560 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10561 mono_domain_lock (domain);
10563 if (!image_is_dynamic (klass->image)) {
10564 mono_class_setup_supertypes (klass);
10566 if (!domain->type_hash)
10567 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10568 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10569 mono_g_hash_table_insert (domain->type_hash, res, type);
10571 mono_domain_unlock (domain);
10572 mono_loader_unlock ();
10576 * LOCKING: Assumes the loader lock is held.
10578 static MonoMethodSignature*
10579 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10581 MonoMethodSignature *sig;
10584 count = parameters? mono_array_length (parameters): 0;
10586 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10587 sig->param_count = count;
10588 sig->sentinelpos = -1; /* FIXME */
10589 for (i = 0; i < count; ++i) {
10590 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10591 mono_error_raise_exception (&error); /* FIXME don't raise here */
10597 * LOCKING: Assumes the loader lock is held.
10599 static MonoMethodSignature*
10600 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10601 MonoMethodSignature *sig;
10603 sig = parameters_to_signature (image, ctor->parameters);
10604 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10605 sig->ret = &mono_defaults.void_class->byval_arg;
10610 * LOCKING: Assumes the loader lock is held.
10612 static MonoMethodSignature*
10613 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10615 MonoMethodSignature *sig;
10617 sig = parameters_to_signature (image, method->parameters);
10618 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10619 if (method->rtype) {
10620 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10621 mono_error_raise_exception (&error); /* FIXME don't raise here */
10623 sig->ret = &mono_defaults.void_class->byval_arg;
10625 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10629 static MonoMethodSignature*
10630 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10632 MonoMethodSignature *sig;
10634 sig = parameters_to_signature (NULL, method->parameters);
10635 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10636 if (method->rtype) {
10637 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10638 mono_error_raise_exception (&error); /* FIXME don't raise here */
10640 sig->ret = &mono_defaults.void_class->byval_arg;
10642 sig->generic_param_count = 0;
10647 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10650 MonoClass *klass = mono_object_class (prop);
10651 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10652 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10653 *name = mono_string_to_utf8 (pb->name);
10654 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10655 mono_error_raise_exception (&error); /* FIXME don't raise here */
10657 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10658 *name = g_strdup (p->property->name);
10659 if (p->property->get)
10660 *type = mono_method_signature (p->property->get)->ret;
10662 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10667 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10670 MonoClass *klass = mono_object_class (field);
10671 if (strcmp (klass->name, "FieldBuilder") == 0) {
10672 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10673 *name = mono_string_to_utf8 (fb->name);
10674 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10675 mono_error_raise_exception (&error); /* FIXME don't raise here */
10677 MonoReflectionField *f = (MonoReflectionField *)field;
10678 *name = g_strdup (mono_field_get_name (f->field));
10679 *type = f->field->type;
10683 #else /* DISABLE_REFLECTION_EMIT */
10686 mono_reflection_register_with_runtime (MonoReflectionType *type)
10688 /* This is empty */
10692 is_sre_type_builder (MonoClass *klass)
10698 is_sre_generic_instance (MonoClass *klass)
10704 init_type_builder_generics (MonoObject *type)
10708 #endif /* !DISABLE_REFLECTION_EMIT */
10712 is_sr_mono_field (MonoClass *klass)
10714 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10718 is_sr_mono_property (MonoClass *klass)
10720 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10724 is_sr_mono_method (MonoClass *klass)
10726 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10730 is_sr_mono_cmethod (MonoClass *klass)
10732 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10736 is_sr_mono_generic_method (MonoClass *klass)
10738 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10742 is_sr_mono_generic_cmethod (MonoClass *klass)
10744 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10748 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10750 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10754 is_usertype (MonoReflectionType *ref)
10756 MonoClass *klass = mono_object_class (ref);
10757 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10760 static MonoReflectionType*
10761 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10763 mono_error_init (error);
10764 if (!type || type->type)
10767 if (is_usertype (type)) {
10768 type = mono_reflection_type_get_underlying_system_type (type, error);
10769 return_val_if_nok (error, NULL);
10770 if (is_usertype (type)) {
10771 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10779 * Encode a value in a custom attribute stream of bytes.
10780 * The value to encode is either supplied as an object in argument val
10781 * (valuetypes are boxed), or as a pointer to the data in the
10783 * @type represents the type of the value
10784 * @buffer is the start of the buffer
10785 * @p the current position in the buffer
10786 * @buflen contains the size of the buffer and is used to return the new buffer size
10787 * if this needs to be realloced.
10788 * @retbuffer and @retp return the start and the position of the buffer
10791 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10794 MonoTypeEnum simple_type;
10796 if ((p-buffer) + 10 >= *buflen) {
10799 newbuf = (char *)g_realloc (buffer, *buflen);
10800 p = newbuf + (p-buffer);
10804 argval = ((char*)arg + sizeof (MonoObject));
10805 simple_type = type->type;
10807 switch (simple_type) {
10808 case MONO_TYPE_BOOLEAN:
10813 case MONO_TYPE_CHAR:
10816 swap_with_size (p, argval, 2, 1);
10822 swap_with_size (p, argval, 4, 1);
10826 swap_with_size (p, argval, 8, 1);
10831 swap_with_size (p, argval, 8, 1);
10834 case MONO_TYPE_VALUETYPE:
10835 if (type->data.klass->enumtype) {
10836 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10839 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10842 case MONO_TYPE_STRING: {
10849 str = mono_string_to_utf8 ((MonoString*)arg);
10850 slen = strlen (str);
10851 if ((p-buffer) + 10 + slen >= *buflen) {
10855 newbuf = (char *)g_realloc (buffer, *buflen);
10856 p = newbuf + (p-buffer);
10859 mono_metadata_encode_value (slen, p, &p);
10860 memcpy (p, str, slen);
10865 case MONO_TYPE_CLASS: {
10868 MonoType *arg_type;
10874 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10875 mono_error_raise_exception (&error); /* FIXME don't raise here */
10876 str = type_get_qualified_name (arg_type, NULL);
10877 slen = strlen (str);
10878 if ((p-buffer) + 10 + slen >= *buflen) {
10882 newbuf = (char *)g_realloc (buffer, *buflen);
10883 p = newbuf + (p-buffer);
10886 mono_metadata_encode_value (slen, p, &p);
10887 memcpy (p, str, slen);
10892 case MONO_TYPE_SZARRAY: {
10894 MonoClass *eclass, *arg_eclass;
10897 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10900 len = mono_array_length ((MonoArray*)arg);
10902 *p++ = (len >> 8) & 0xff;
10903 *p++ = (len >> 16) & 0xff;
10904 *p++ = (len >> 24) & 0xff;
10906 *retbuffer = buffer;
10907 eclass = type->data.klass;
10908 arg_eclass = mono_object_class (arg)->element_class;
10911 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10912 eclass = mono_defaults.object_class;
10914 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10915 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10916 int elsize = mono_class_array_element_size (arg_eclass);
10917 for (i = 0; i < len; ++i) {
10918 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10921 } else if (eclass->valuetype && arg_eclass->valuetype) {
10922 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10923 int elsize = mono_class_array_element_size (eclass);
10924 for (i = 0; i < len; ++i) {
10925 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10929 for (i = 0; i < len; ++i) {
10930 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10935 case MONO_TYPE_OBJECT: {
10941 * The parameter type is 'object' but the type of the actual
10942 * argument is not. So we have to add type information to the blob
10943 * too. This is completely undocumented in the spec.
10947 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10952 klass = mono_object_class (arg);
10954 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10957 } else if (klass->enumtype) {
10959 } else if (klass == mono_defaults.string_class) {
10960 simple_type = MONO_TYPE_STRING;
10963 } else if (klass->rank == 1) {
10965 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10966 /* See Partition II, Appendix B3 */
10969 *p++ = klass->element_class->byval_arg.type;
10970 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10972 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10973 *p++ = simple_type = klass->byval_arg.type;
10976 g_error ("unhandled type in custom attr");
10978 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10979 slen = strlen (str);
10980 if ((p-buffer) + 10 + slen >= *buflen) {
10984 newbuf = (char *)g_realloc (buffer, *buflen);
10985 p = newbuf + (p-buffer);
10988 mono_metadata_encode_value (slen, p, &p);
10989 memcpy (p, str, slen);
10992 simple_type = mono_class_enum_basetype (klass)->type;
10996 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10999 *retbuffer = buffer;
11003 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11005 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11006 char *str = type_get_qualified_name (type, NULL);
11007 int slen = strlen (str);
11011 * This seems to be optional...
11014 mono_metadata_encode_value (slen, p, &p);
11015 memcpy (p, str, slen);
11018 } else if (type->type == MONO_TYPE_OBJECT) {
11020 } else if (type->type == MONO_TYPE_CLASS) {
11021 /* it should be a type: encode_cattr_value () has the check */
11024 mono_metadata_encode_value (type->type, p, &p);
11025 if (type->type == MONO_TYPE_SZARRAY)
11026 /* See the examples in Partition VI, Annex B */
11027 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11033 #ifndef DISABLE_REFLECTION_EMIT
11035 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11038 /* Preallocate a large enough buffer */
11039 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11040 char *str = type_get_qualified_name (type, NULL);
11041 len = strlen (str);
11043 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11044 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11045 len = strlen (str);
11050 len += strlen (name);
11052 if ((p-buffer) + 20 + len >= *buflen) {
11056 newbuf = (char *)g_realloc (buffer, *buflen);
11057 p = newbuf + (p-buffer);
11061 encode_field_or_prop_type (type, p, &p);
11063 len = strlen (name);
11064 mono_metadata_encode_value (len, p, &p);
11065 memcpy (p, name, len);
11067 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11069 *retbuffer = buffer;
11073 * mono_reflection_get_custom_attrs_blob:
11074 * @ctor: custom attribute constructor
11075 * @ctorArgs: arguments o the constructor
11081 * Creates the blob of data that needs to be saved in the metadata and that represents
11082 * the custom attributed described by @ctor, @ctorArgs etc.
11083 * Returns: a Byte array representing the blob of data.
11086 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11089 MonoMethodSignature *sig;
11094 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11095 /* sig is freed later so allocate it in the heap */
11096 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11098 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11101 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11103 p = buffer = (char *)g_malloc (buflen);
11104 /* write the prolog */
11107 for (i = 0; i < sig->param_count; ++i) {
11108 arg = mono_array_get (ctorArgs, MonoObject*, i);
11109 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11113 i += mono_array_length (properties);
11115 i += mono_array_length (fields);
11117 *p++ = (i >> 8) & 0xff;
11120 for (i = 0; i < mono_array_length (properties); ++i) {
11124 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11125 get_prop_name_and_type (prop, &pname, &ptype);
11126 *p++ = 0x54; /* PROPERTY signature */
11127 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11134 for (i = 0; i < mono_array_length (fields); ++i) {
11138 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11139 get_field_name_and_type (field, &fname, &ftype);
11140 *p++ = 0x53; /* FIELD signature */
11141 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11146 g_assert (p - buffer <= buflen);
11147 buflen = p - buffer;
11148 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11149 p = mono_array_addr (result, char, 0);
11150 memcpy (p, buffer, buflen);
11152 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11158 * mono_reflection_setup_internal_class:
11159 * @tb: a TypeBuilder object
11161 * Creates a MonoClass that represents the TypeBuilder.
11162 * This is a trick that lets us simplify a lot of reflection code
11163 * (and will allow us to support Build and Run assemblies easier).
11166 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11169 MonoClass *klass, *parent;
11171 RESOLVE_TYPE (tb->parent, &error);
11172 mono_error_raise_exception (&error); /* FIXME don't raise here */
11174 mono_loader_lock ();
11177 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11178 if (!is_ok (&error)) {
11179 mono_loader_unlock ();
11180 mono_error_raise_exception (&error); /* FIXME don't raise here */
11182 /* check so we can compile corlib correctly */
11183 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11184 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11185 parent = parent_type->data.klass;
11187 parent = mono_class_from_mono_type (parent_type);
11193 /* the type has already being created: it means we just have to change the parent */
11194 if (tb->type.type) {
11195 klass = mono_class_from_mono_type (tb->type.type);
11196 klass->parent = NULL;
11197 /* fool mono_class_setup_parent */
11198 klass->supertypes = NULL;
11199 mono_class_setup_parent (klass, parent);
11200 mono_class_setup_mono_type (klass);
11201 mono_loader_unlock ();
11205 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11207 klass->image = &tb->module->dynamic_image->image;
11209 klass->inited = 1; /* we lie to the runtime */
11210 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11211 if (!mono_error_ok (&error))
11213 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11214 if (!mono_error_ok (&error))
11216 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11217 klass->flags = tb->attrs;
11219 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11221 klass->element_class = klass;
11223 if (mono_class_get_ref_info (klass) == NULL) {
11225 mono_class_set_ref_info (klass, tb);
11227 /* Put into cache so mono_class_get_checked () will find it.
11228 Skip nested types as those should not be available on the global scope. */
11229 if (!tb->nesting_type)
11230 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11233 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11234 by performing a mono_class_get which does the full resolution.
11236 Working around this semantics would require us to write a lot of code for no clear advantage.
11238 mono_image_append_class_to_reflection_info_set (klass);
11240 g_assert (mono_class_get_ref_info (klass) == tb);
11243 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11245 if (parent != NULL) {
11246 mono_class_setup_parent (klass, parent);
11247 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11248 const char *old_n = klass->name;
11249 /* trick to get relative numbering right when compiling corlib */
11250 klass->name = "BuildingObject";
11251 mono_class_setup_parent (klass, mono_defaults.object_class);
11252 klass->name = old_n;
11255 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11256 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11257 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11258 klass->instance_size = sizeof (MonoObject);
11259 klass->size_inited = 1;
11260 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11263 mono_class_setup_mono_type (klass);
11265 mono_class_setup_supertypes (klass);
11268 * FIXME: handle interfaces.
11271 tb->type.type = &klass->byval_arg;
11273 if (tb->nesting_type) {
11274 g_assert (tb->nesting_type->type);
11275 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11276 if (!is_ok (&error)) goto failure;
11277 klass->nested_in = mono_class_from_mono_type (nesting_type);
11280 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11282 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11284 mono_loader_unlock ();
11288 mono_loader_unlock ();
11289 mono_error_raise_exception (&error);
11293 * mono_reflection_setup_generic_class:
11294 * @tb: a TypeBuilder object
11296 * Setup the generic class before adding the first generic parameter.
11299 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11304 * mono_reflection_create_generic_class:
11305 * @tb: a TypeBuilder object
11307 * Creates the generic class after all generic parameters have been added.
11310 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11316 klass = mono_class_from_mono_type (tb->type.type);
11318 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11320 if (klass->generic_container || (count == 0))
11323 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11325 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11327 klass->generic_container->owner.klass = klass;
11328 klass->generic_container->type_argc = count;
11329 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11331 klass->is_generic = 1;
11333 for (i = 0; i < count; i++) {
11334 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11335 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11336 mono_error_raise_exception (&error); /* FIXME don't raise here */
11337 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11338 klass->generic_container->type_params [i] = *param;
11339 /*Make sure we are a diferent type instance */
11340 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11341 klass->generic_container->type_params [i].info.pklass = NULL;
11342 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11344 g_assert (klass->generic_container->type_params [i].param.owner);
11347 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11351 * mono_reflection_create_internal_class:
11352 * @tb: a TypeBuilder object
11354 * Actually create the MonoClass that is associated with the TypeBuilder.
11357 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11362 klass = mono_class_from_mono_type (tb->type.type);
11364 mono_loader_lock ();
11365 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11366 MonoReflectionFieldBuilder *fb;
11368 MonoType *enum_basetype;
11370 g_assert (tb->fields != NULL);
11371 g_assert (mono_array_length (tb->fields) >= 1);
11373 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11375 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11376 if (!is_ok (&error)) {
11377 mono_loader_unlock ();
11378 mono_error_raise_exception (&error); /* FIXME don't raise here */
11380 if (!mono_type_is_valid_enum_basetype (field_type)) {
11381 mono_loader_unlock ();
11385 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11386 if (!is_ok (&error)) {
11387 mono_loader_unlock ();
11388 mono_error_raise_exception (&error); /* FIXME don't raise here */
11390 klass->element_class = mono_class_from_mono_type (enum_basetype);
11391 if (!klass->element_class)
11392 klass->element_class = mono_class_from_mono_type (enum_basetype);
11395 * get the element_class from the current corlib.
11397 ec = default_class_from_mono_type (enum_basetype);
11398 klass->instance_size = ec->instance_size;
11399 klass->size_inited = 1;
11401 * this is almost safe to do with enums and it's needed to be able
11402 * to create objects of the enum type (for use in SetConstant).
11404 /* FIXME: Does this mean enums can't have method overrides ? */
11405 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11407 mono_loader_unlock ();
11410 static MonoMarshalSpec*
11411 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11412 MonoReflectionMarshal *minfo)
11415 MonoMarshalSpec *res;
11417 res = image_g_new0 (image, MonoMarshalSpec, 1);
11418 res->native = (MonoMarshalNative)minfo->type;
11420 switch (minfo->type) {
11421 case MONO_NATIVE_LPARRAY:
11422 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11423 if (minfo->has_size) {
11424 res->data.array_data.param_num = minfo->param_num;
11425 res->data.array_data.num_elem = minfo->count;
11426 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11429 res->data.array_data.param_num = -1;
11430 res->data.array_data.num_elem = -1;
11431 res->data.array_data.elem_mult = -1;
11435 case MONO_NATIVE_BYVALTSTR:
11436 case MONO_NATIVE_BYVALARRAY:
11437 res->data.array_data.num_elem = minfo->count;
11440 case MONO_NATIVE_CUSTOM:
11441 if (minfo->marshaltyperef) {
11442 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11443 mono_error_raise_exception (&error); /* FIXME don't raise here */
11444 res->data.custom_data.custom_name =
11445 type_get_fully_qualified_name (marshaltyperef);
11447 if (minfo->mcookie)
11448 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11457 #endif /* !DISABLE_REFLECTION_EMIT */
11459 MonoReflectionMarshalAsAttribute*
11460 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11461 MonoMarshalSpec *spec, MonoError *error)
11463 MonoReflectionType *rt;
11464 MonoReflectionMarshalAsAttribute *minfo;
11467 mono_error_init (error);
11469 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11472 minfo->utype = spec->native;
11474 switch (minfo->utype) {
11475 case MONO_NATIVE_LPARRAY:
11476 minfo->array_subtype = spec->data.array_data.elem_type;
11477 minfo->size_const = spec->data.array_data.num_elem;
11478 if (spec->data.array_data.param_num != -1)
11479 minfo->size_param_index = spec->data.array_data.param_num;
11482 case MONO_NATIVE_BYVALTSTR:
11483 case MONO_NATIVE_BYVALARRAY:
11484 minfo->size_const = spec->data.array_data.num_elem;
11487 case MONO_NATIVE_CUSTOM:
11488 if (spec->data.custom_data.custom_name) {
11489 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11491 rt = mono_type_get_object_checked (domain, mtype, error);
11495 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11498 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11500 if (spec->data.custom_data.cookie)
11501 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11511 #ifndef DISABLE_REFLECTION_EMIT
11513 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11514 ReflectionMethodBuilder *rmb,
11515 MonoMethodSignature *sig)
11519 MonoMethodWrapper *wrapperm;
11520 MonoMarshalSpec **specs;
11521 MonoReflectionMethodAux *method_aux;
11526 mono_error_init (&error);
11528 * Methods created using a MethodBuilder should have their memory allocated
11529 * inside the image mempool, while dynamic methods should have their memory
11532 dynamic = rmb->refs != NULL;
11533 image = dynamic ? NULL : klass->image;
11536 g_assert (!klass->generic_class);
11538 mono_loader_lock ();
11540 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11541 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11542 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11544 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11546 wrapperm = (MonoMethodWrapper*)m;
11548 m->dynamic = dynamic;
11550 m->flags = rmb->attrs;
11551 m->iflags = rmb->iattrs;
11552 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11554 m->signature = sig;
11555 m->sre_method = TRUE;
11556 m->skip_visibility = rmb->skip_visibility;
11557 if (rmb->table_idx)
11558 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11560 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11561 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11562 m->string_ctor = 1;
11564 m->signature->pinvoke = 1;
11565 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11566 m->signature->pinvoke = 1;
11568 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11570 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11571 g_assert (mono_error_ok (&error));
11572 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11573 g_assert (mono_error_ok (&error));
11575 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11577 if (image_is_dynamic (klass->image))
11578 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11580 mono_loader_unlock ();
11583 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11584 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11585 MonoMethodHeader *header;
11587 gint32 max_stack, i;
11588 gint32 num_locals = 0;
11589 gint32 num_clauses = 0;
11593 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11594 code_size = rmb->ilgen->code_len;
11595 max_stack = rmb->ilgen->max_stack;
11596 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11597 if (rmb->ilgen->ex_handlers)
11598 num_clauses = method_count_clauses (rmb->ilgen);
11601 code = mono_array_addr (rmb->code, guint8, 0);
11602 code_size = mono_array_length (rmb->code);
11603 /* we probably need to run a verifier on the code... */
11613 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11614 header->code_size = code_size;
11615 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11616 memcpy ((char*)header->code, code, code_size);
11617 header->max_stack = max_stack;
11618 header->init_locals = rmb->init_locals;
11619 header->num_locals = num_locals;
11621 for (i = 0; i < num_locals; ++i) {
11622 MonoReflectionLocalBuilder *lb =
11623 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11625 header->locals [i] = image_g_new0 (image, MonoType, 1);
11626 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11627 mono_error_assert_ok (&error);
11628 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11631 header->num_clauses = num_clauses;
11633 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11634 rmb->ilgen, num_clauses, &error);
11635 mono_error_assert_ok (&error);
11638 wrapperm->header = header;
11641 if (rmb->generic_params) {
11642 int count = mono_array_length (rmb->generic_params);
11643 MonoGenericContainer *container = rmb->generic_container;
11645 g_assert (container);
11647 container->type_argc = count;
11648 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11649 container->owner.method = m;
11650 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11652 m->is_generic = TRUE;
11653 mono_method_set_generic_container (m, container);
11655 for (i = 0; i < count; i++) {
11656 MonoReflectionGenericParam *gp =
11657 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11658 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11659 mono_error_assert_ok (&error);
11660 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11661 container->type_params [i] = *param;
11665 * The method signature might have pointers to generic parameters that belong to other methods.
11666 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11667 * generic parameters.
11669 for (i = 0; i < m->signature->param_count; ++i) {
11670 MonoType *t = m->signature->params [i];
11671 if (t->type == MONO_TYPE_MVAR) {
11672 MonoGenericParam *gparam = t->data.generic_param;
11673 if (gparam->num < count) {
11674 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11675 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11681 if (klass->generic_container) {
11682 container->parent = klass->generic_container;
11683 container->context.class_inst = klass->generic_container->context.class_inst;
11685 container->context.method_inst = mono_get_shared_generic_inst (container);
11689 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11693 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11695 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11696 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11697 for (i = 0; i < rmb->nrefs; ++i)
11698 data [i + 1] = rmb->refs [i];
11703 /* Parameter info */
11706 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11707 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11708 for (i = 0; i <= m->signature->param_count; ++i) {
11709 MonoReflectionParamBuilder *pb;
11710 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11711 if ((i > 0) && (pb->attrs)) {
11712 /* Make a copy since it might point to a shared type structure */
11713 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11714 m->signature->params [i - 1]->attrs = pb->attrs;
11717 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11718 MonoDynamicImage *assembly;
11720 MonoTypeEnum def_type;
11724 if (!method_aux->param_defaults) {
11725 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11726 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11728 assembly = (MonoDynamicImage*)klass->image;
11729 idx = encode_constant (assembly, pb->def_value, &def_type);
11730 /* Copy the data from the blob since it might get realloc-ed */
11731 p = assembly->blob.data + idx;
11732 len = mono_metadata_decode_blob_size (p, &p2);
11734 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11735 method_aux->param_default_types [i] = def_type;
11736 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11740 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11741 g_assert (mono_error_ok (&error));
11744 if (!method_aux->param_cattr)
11745 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11746 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11752 /* Parameter marshalling */
11755 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11756 MonoReflectionParamBuilder *pb;
11757 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11758 if (pb->marshal_info) {
11760 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11761 specs [pb->position] =
11762 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11766 if (specs != NULL) {
11768 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11769 method_aux->param_marshall = specs;
11772 if (image_is_dynamic (klass->image) && method_aux)
11773 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11775 mono_loader_unlock ();
11781 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11783 ReflectionMethodBuilder rmb;
11784 MonoMethodSignature *sig;
11786 mono_loader_lock ();
11787 sig = ctor_builder_to_signature (klass->image, mb);
11788 mono_loader_unlock ();
11790 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11793 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11794 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11796 /* If we are in a generic class, we might be called multiple times from inflate_method */
11797 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11798 /* ilgen is no longer needed */
11802 return mb->mhandle;
11806 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11808 ReflectionMethodBuilder rmb;
11809 MonoMethodSignature *sig;
11811 mono_error_init (error);
11813 mono_loader_lock ();
11814 sig = method_builder_to_signature (klass->image, mb);
11815 mono_loader_unlock ();
11817 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11820 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11821 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11823 /* If we are in a generic class, we might be called multiple times from inflate_method */
11824 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11825 /* ilgen is no longer needed */
11828 return mb->mhandle;
11831 static MonoClassField*
11832 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11834 MonoClassField *field;
11838 field = g_new0 (MonoClassField, 1);
11840 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11841 g_assert (mono_error_ok (&error));
11842 if (fb->attrs || fb->modreq || fb->modopt) {
11843 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11844 if (!is_ok (&error)) {
11846 mono_error_raise_exception (&error); /* FIXME don't raise here */
11848 field->type = mono_metadata_type_dup (NULL, type);
11849 field->type->attrs = fb->attrs;
11851 g_assert (image_is_dynamic (klass->image));
11852 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11853 g_free (field->type);
11854 field->type = mono_metadata_type_dup (klass->image, custom);
11857 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11858 if (!is_ok (&error)) {
11860 mono_error_raise_exception (&error); /* FIXME don't raise here */
11863 if (fb->offset != -1)
11864 field->offset = fb->offset;
11865 field->parent = klass;
11866 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11868 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11875 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11879 MonoReflectionTypeBuilder *tb = NULL;
11880 gboolean is_dynamic = FALSE;
11881 MonoClass *geninst;
11883 mono_loader_lock ();
11885 if (is_sre_type_builder (mono_object_class (type))) {
11886 tb = (MonoReflectionTypeBuilder *) type;
11889 } else if (is_sre_generic_instance (mono_object_class (type))) {
11890 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11891 MonoReflectionType *gtd = rgi->generic_type;
11893 if (is_sre_type_builder (mono_object_class (gtd))) {
11894 tb = (MonoReflectionTypeBuilder *)gtd;
11899 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11900 if (tb && tb->generic_container)
11901 mono_reflection_create_generic_class (tb);
11903 MonoType *t = mono_reflection_type_get_handle (type, &error);
11904 mono_error_raise_exception (&error); /* FIXME don't raise here */
11906 klass = mono_class_from_mono_type (t);
11907 if (!klass->generic_container) {
11908 mono_loader_unlock ();
11912 if (klass->wastypebuilder) {
11913 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11918 mono_loader_unlock ();
11920 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11922 return &geninst->byval_arg;
11926 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11928 MonoGenericClass *gclass;
11929 MonoGenericInst *inst;
11931 g_assert (klass->generic_container);
11933 inst = mono_metadata_get_generic_inst (type_argc, types);
11934 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11936 return mono_generic_class_get_class (gclass);
11939 MonoReflectionMethod*
11940 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11944 MonoMethod *method, *inflated;
11945 MonoMethodInflated *imethod;
11946 MonoGenericContext tmp_context;
11947 MonoGenericInst *ginst;
11948 MonoType **type_argv;
11951 /*FIXME but this no longer should happen*/
11952 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11953 #ifndef DISABLE_REFLECTION_EMIT
11954 MonoReflectionMethodBuilder *mb = NULL;
11958 mb = (MonoReflectionMethodBuilder *) rmethod;
11959 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11960 mono_error_raise_exception (&error); /* FIXME don't raise here */
11961 klass = mono_class_from_mono_type (tb);
11963 method = methodbuilder_to_mono_method (klass, mb, &error);
11965 mono_error_raise_exception (&error); /* FIXME don't raise here */
11967 g_assert_not_reached ();
11971 method = rmethod->method;
11974 klass = method->klass;
11976 if (method->is_inflated)
11977 method = ((MonoMethodInflated *) method)->declaring;
11979 count = mono_method_signature (method)->generic_param_count;
11980 if (count != mono_array_length (types))
11983 type_argv = g_new0 (MonoType *, count);
11984 for (i = 0; i < count; i++) {
11985 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11986 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11987 if (!is_ok (&error)) {
11988 g_free (type_argv);
11989 mono_error_raise_exception (&error); /* FIXME don't raise here */
11992 ginst = mono_metadata_get_generic_inst (count, type_argv);
11993 g_free (type_argv);
11995 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11996 tmp_context.method_inst = ginst;
11998 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11999 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12000 imethod = (MonoMethodInflated *) inflated;
12002 /*FIXME but I think this is no longer necessary*/
12003 if (image_is_dynamic (method->klass->image)) {
12004 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12006 * This table maps metadata structures representing inflated methods/fields
12007 * to the reflection objects representing their generic definitions.
12009 mono_image_lock ((MonoImage*)image);
12010 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12011 mono_image_unlock ((MonoImage*)image);
12014 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12015 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12017 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12018 mono_error_raise_exception (&error); /* FIXME don't raise here */
12022 #ifndef DISABLE_REFLECTION_EMIT
12024 static MonoMethod *
12025 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12027 MonoMethodInflated *imethod;
12028 MonoGenericContext *context;
12032 * With generic code sharing the klass might not be inflated.
12033 * This can happen because classes inflated with their own
12034 * type arguments are "normalized" to the uninflated class.
12036 if (!klass->generic_class)
12039 context = mono_class_get_context (klass);
12041 if (klass->method.count && klass->methods) {
12042 /* Find the already created inflated method */
12043 for (i = 0; i < klass->method.count; ++i) {
12044 g_assert (klass->methods [i]->is_inflated);
12045 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12048 g_assert (i < klass->method.count);
12049 imethod = (MonoMethodInflated*)klass->methods [i];
12052 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12053 mono_error_assert_ok (&error);
12056 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12057 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12059 mono_image_lock ((MonoImage*)image);
12060 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12061 mono_image_unlock ((MonoImage*)image);
12063 return (MonoMethod *) imethod;
12066 static MonoMethod *
12067 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12069 MonoMethod *method;
12072 mono_error_init (error);
12074 MonoClass *type_class = mono_object_class (type);
12076 if (is_sre_generic_instance (type_class)) {
12077 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12078 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12079 return_val_if_nok (error, NULL);
12080 gklass = mono_class_from_mono_type (generic_type);
12081 } else if (is_sre_type_builder (type_class)) {
12082 MonoType *t = mono_reflection_type_get_handle (type, error);
12083 return_val_if_nok (error, NULL);
12084 gklass = mono_class_from_mono_type (t);
12085 } else if (type->type) {
12086 gklass = mono_class_from_mono_type (type->type);
12087 gklass = mono_class_get_generic_type_definition (gklass);
12089 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12092 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12093 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12094 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12096 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12100 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12101 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12104 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12105 method = ((MonoReflectionMethod *) obj)->method;
12107 method = NULL; /* prevent compiler warning */
12108 g_error ("can't handle type %s", obj->vtable->klass->name);
12111 MonoType *t = mono_reflection_type_get_handle (type, error);
12112 return_val_if_nok (error, NULL);
12113 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12116 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12118 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12121 MonoGenericClass *gclass;
12122 MonoDynamicGenericClass *dgclass;
12123 MonoClass *klass, *gklass;
12127 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12128 mono_error_raise_exception (&error); /* FIXME don't raise here */
12129 klass = mono_class_from_mono_type (gtype);
12130 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12131 gclass = gtype->data.generic_class;
12133 if (!gclass->is_dynamic)
12136 dgclass = (MonoDynamicGenericClass *) gclass;
12138 if (dgclass->initialized)
12141 gklass = gclass->container_class;
12142 mono_class_init (gklass);
12144 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12146 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12147 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12148 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12150 for (i = 0; i < dgclass->count_fields; i++) {
12152 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12153 MonoClassField *field, *inflated_field = NULL;
12155 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12156 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12157 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12158 field = ((MonoReflectionField *) obj)->field;
12160 field = NULL; /* prevent compiler warning */
12161 g_assert_not_reached ();
12164 dgclass->fields [i] = *field;
12165 dgclass->fields [i].parent = klass;
12166 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12167 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12168 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12169 dgclass->field_generic_types [i] = field->type;
12170 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12171 dgclass->field_objects [i] = obj;
12173 if (inflated_field) {
12174 g_free (inflated_field);
12176 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12180 dgclass->initialized = TRUE;
12184 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12186 MonoDynamicGenericClass *dgclass;
12189 g_assert (gclass->is_dynamic);
12191 dgclass = (MonoDynamicGenericClass *)gclass;
12193 for (i = 0; i < dgclass->count_fields; ++i) {
12194 MonoClassField *field = dgclass->fields + i;
12195 mono_metadata_free_type (field->type);
12196 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12201 fix_partial_generic_class (MonoClass *klass)
12203 MonoClass *gklass = klass->generic_class->container_class;
12204 MonoDynamicGenericClass *dgclass;
12207 if (klass->wastypebuilder)
12210 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12211 if (klass->parent != gklass->parent) {
12213 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12214 if (mono_error_ok (&error)) {
12215 MonoClass *parent = mono_class_from_mono_type (parent_type);
12216 mono_metadata_free_type (parent_type);
12217 if (parent != klass->parent) {
12218 /*fool mono_class_setup_parent*/
12219 klass->supertypes = NULL;
12220 mono_class_setup_parent (klass, parent);
12223 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12224 mono_error_cleanup (&error);
12225 if (gklass->wastypebuilder)
12226 klass->wastypebuilder = TRUE;
12231 if (!dgclass->initialized)
12234 if (klass->method.count != gklass->method.count) {
12235 klass->method.count = gklass->method.count;
12236 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12238 for (i = 0; i < klass->method.count; i++) {
12240 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12241 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12242 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12246 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12247 klass->interface_count = gklass->interface_count;
12248 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12249 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12251 for (i = 0; i < gklass->interface_count; ++i) {
12253 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12254 mono_error_raise_exception (&error); /* FIXME don't raise here */
12256 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12257 mono_metadata_free_type (iface_type);
12259 ensure_runtime_vtable (klass->interfaces [i], &error);
12260 mono_error_raise_exception (&error); /* FIXME don't raise here */
12262 klass->interfaces_inited = 1;
12265 if (klass->field.count != gklass->field.count) {
12266 klass->field.count = gklass->field.count;
12267 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12269 for (i = 0; i < klass->field.count; i++) {
12271 klass->fields [i] = gklass->fields [i];
12272 klass->fields [i].parent = klass;
12273 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12274 mono_error_raise_exception (&error); /* FIXME don't raise here */
12278 /*We can only finish with this klass once it's parent has as well*/
12279 if (gklass->wastypebuilder)
12280 klass->wastypebuilder = TRUE;
12285 * ensure_generic_class_runtime_vtable:
12286 * @klass a generic class
12287 * @error set on error
12289 * Ensures that the generic container of @klass has a vtable and
12290 * returns TRUE on success. On error returns FALSE and sets @error.
12293 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12295 MonoClass *gklass = klass->generic_class->container_class;
12297 mono_error_init (error);
12299 if (!ensure_runtime_vtable (gklass, error))
12302 fix_partial_generic_class (klass);
12308 * ensure_runtime_vtable:
12310 * @error set on error
12312 * Ensures that @klass has a vtable and returns TRUE on success. On
12313 * error returns FALSE and sets @error.
12316 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12318 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12321 mono_error_init (error);
12323 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12326 if (!ensure_runtime_vtable (klass->parent, error))
12330 num = tb->ctors? mono_array_length (tb->ctors): 0;
12331 num += tb->num_methods;
12332 klass->method.count = num;
12333 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12334 num = tb->ctors? mono_array_length (tb->ctors): 0;
12335 for (i = 0; i < num; ++i) {
12336 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12339 klass->methods [i] = ctor;
12341 num = tb->num_methods;
12343 for (i = 0; i < num; ++i) {
12344 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12347 klass->methods [j++] = meth;
12350 if (tb->interfaces) {
12351 klass->interface_count = mono_array_length (tb->interfaces);
12352 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12353 for (i = 0; i < klass->interface_count; ++i) {
12354 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12355 return_val_if_nok (error, FALSE);
12356 klass->interfaces [i] = mono_class_from_mono_type (iface);
12357 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12360 klass->interfaces_inited = 1;
12362 } else if (klass->generic_class){
12363 if (!ensure_generic_class_runtime_vtable (klass, error))
12367 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12369 for (i = 0; i < klass->method.count; ++i) {
12370 MonoMethod *im = klass->methods [i];
12371 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12372 im->slot = slot_num++;
12375 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12376 mono_class_setup_interface_offsets (klass);
12377 mono_class_setup_interface_id (klass);
12381 * The generic vtable is needed even if image->run is not set since some
12382 * runtime code like ves_icall_Type_GetMethodsByName depends on
12383 * method->slot being defined.
12387 * tb->methods could not be freed since it is used for determining
12388 * overrides during dynamic vtable construction.
12395 mono_reflection_method_get_handle (MonoObject *method)
12398 MonoClass *klass = mono_object_class (method);
12399 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12400 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12401 return sr_method->method;
12403 if (is_sre_method_builder (klass)) {
12404 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12405 return mb->mhandle;
12407 if (is_sre_method_on_tb_inst (klass)) {
12408 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12409 MonoMethod *result;
12410 /*FIXME move this to a proper method and unify with resolve_object*/
12411 if (m->method_args) {
12412 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12413 mono_error_raise_exception (&error); /* FIXME don't raise here */
12415 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12416 mono_error_raise_exception (&error); /* FIXME don't raise here */
12417 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12418 MonoMethod *mono_method;
12420 if (is_sre_method_builder (mono_object_class (m->mb)))
12421 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12422 else if (is_sr_mono_method (mono_object_class (m->mb)))
12423 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12425 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)));
12427 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12432 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12437 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12439 MonoReflectionTypeBuilder *tb;
12441 MonoReflectionMethod *m;
12444 *num_overrides = 0;
12446 g_assert (image_is_dynamic (klass->image));
12448 if (!mono_class_get_ref_info (klass))
12451 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12453 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12457 for (i = 0; i < tb->num_methods; ++i) {
12458 MonoReflectionMethodBuilder *mb =
12459 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12460 if (mb->override_methods)
12461 onum += mono_array_length (mb->override_methods);
12466 *overrides = g_new0 (MonoMethod*, onum * 2);
12469 for (i = 0; i < tb->num_methods; ++i) {
12470 MonoReflectionMethodBuilder *mb =
12471 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12472 if (mb->override_methods) {
12473 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12474 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12476 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12477 (*overrides) [onum * 2 + 1] = mb->mhandle;
12479 g_assert (mb->mhandle);
12487 *num_overrides = onum;
12491 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12493 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12494 MonoReflectionFieldBuilder *fb;
12495 MonoClassField *field;
12496 MonoImage *image = klass->image;
12497 const char *p, *p2;
12499 guint32 len, idx, real_size = 0;
12501 klass->field.count = tb->num_fields;
12502 klass->field.first = 0;
12504 mono_error_init (error);
12506 if (tb->class_size) {
12507 if ((tb->packing_size & 0xffffff00) != 0) {
12508 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12509 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12512 klass->packing_size = tb->packing_size;
12513 real_size = klass->instance_size + tb->class_size;
12516 if (!klass->field.count) {
12517 klass->instance_size = MAX (klass->instance_size, real_size);
12521 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12522 mono_class_alloc_ext (klass);
12523 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12525 This is, guess what, a hack.
12526 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12527 On the static path no field class is resolved, only types are built. This is the right thing to do
12529 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12531 klass->size_inited = 1;
12533 for (i = 0; i < klass->field.count; ++i) {
12534 MonoArray *rva_data;
12535 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12536 field = &klass->fields [i];
12537 field->name = mono_string_to_utf8_image (image, fb->name, error);
12538 if (!mono_error_ok (error))
12541 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12542 return_if_nok (error);
12543 field->type = mono_metadata_type_dup (klass->image, type);
12544 field->type->attrs = fb->attrs;
12546 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12547 return_if_nok (error);
12550 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12551 char *base = mono_array_addr (rva_data, char, 0);
12552 size_t size = mono_array_length (rva_data);
12553 char *data = (char *)mono_image_alloc (klass->image, size);
12554 memcpy (data, base, size);
12555 klass->ext->field_def_values [i].data = data;
12557 if (fb->offset != -1)
12558 field->offset = fb->offset;
12559 field->parent = klass;
12560 fb->handle = field;
12561 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12563 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12564 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12566 if (fb->def_value) {
12567 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12568 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12569 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12570 /* Copy the data from the blob since it might get realloc-ed */
12571 p = assembly->blob.data + idx;
12572 len = mono_metadata_decode_blob_size (p, &p2);
12574 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12575 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12579 klass->instance_size = MAX (klass->instance_size, real_size);
12580 mono_class_layout_fields (klass);
12584 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12586 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12587 MonoReflectionPropertyBuilder *pb;
12588 MonoImage *image = klass->image;
12589 MonoProperty *properties;
12592 mono_error_init (error);
12595 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12597 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12598 klass->ext->property.first = 0;
12600 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12601 klass->ext->properties = properties;
12602 for (i = 0; i < klass->ext->property.count; ++i) {
12603 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12604 properties [i].parent = klass;
12605 properties [i].attrs = pb->attrs;
12606 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12607 if (!mono_error_ok (error))
12609 if (pb->get_method)
12610 properties [i].get = pb->get_method->mhandle;
12611 if (pb->set_method)
12612 properties [i].set = pb->set_method->mhandle;
12614 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12615 if (pb->def_value) {
12617 const char *p, *p2;
12618 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12619 if (!klass->ext->prop_def_values)
12620 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12621 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12622 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12623 /* Copy the data from the blob since it might get realloc-ed */
12624 p = assembly->blob.data + idx;
12625 len = mono_metadata_decode_blob_size (p, &p2);
12627 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12628 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12633 MonoReflectionEvent *
12634 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12637 MonoEvent *event = g_new0 (MonoEvent, 1);
12640 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12641 mono_error_raise_exception (&error); /* FIXME don't raise here */
12642 klass = mono_class_from_mono_type (type);
12644 event->parent = klass;
12645 event->attrs = eb->attrs;
12646 event->name = mono_string_to_utf8 (eb->name);
12647 if (eb->add_method)
12648 event->add = eb->add_method->mhandle;
12649 if (eb->remove_method)
12650 event->remove = eb->remove_method->mhandle;
12651 if (eb->raise_method)
12652 event->raise = eb->raise_method->mhandle;
12654 #ifndef MONO_SMALL_CONFIG
12655 if (eb->other_methods) {
12657 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12658 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12659 MonoReflectionMethodBuilder *mb =
12660 mono_array_get (eb->other_methods,
12661 MonoReflectionMethodBuilder*, j);
12662 event->other [j] = mb->mhandle;
12667 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12668 mono_error_raise_exception (&error); /* FIXME don't raise here */
12673 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12675 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12676 MonoReflectionEventBuilder *eb;
12677 MonoImage *image = klass->image;
12681 mono_error_init (error);
12684 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12686 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12687 klass->ext->event.first = 0;
12689 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12690 klass->ext->events = events;
12691 for (i = 0; i < klass->ext->event.count; ++i) {
12692 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12693 events [i].parent = klass;
12694 events [i].attrs = eb->attrs;
12695 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12696 if (!mono_error_ok (error))
12698 if (eb->add_method)
12699 events [i].add = eb->add_method->mhandle;
12700 if (eb->remove_method)
12701 events [i].remove = eb->remove_method->mhandle;
12702 if (eb->raise_method)
12703 events [i].raise = eb->raise_method->mhandle;
12705 #ifndef MONO_SMALL_CONFIG
12706 if (eb->other_methods) {
12708 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12709 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12710 MonoReflectionMethodBuilder *mb =
12711 mono_array_get (eb->other_methods,
12712 MonoReflectionMethodBuilder*, j);
12713 events [i].other [j] = mb->mhandle;
12717 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12722 remove_instantiations_of_and_ensure_contents (gpointer key,
12724 gpointer user_data)
12726 MonoType *type = (MonoType*)key;
12727 MonoClass *klass = (MonoClass*)user_data;
12729 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12730 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12737 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12739 mono_error_init (error);
12745 for (i = 0; i < mono_array_length (arr); ++i) {
12746 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12747 if (!mono_error_ok (error))
12752 MonoReflectionType*
12753 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12757 MonoDomain* domain;
12758 MonoReflectionType* res;
12761 domain = mono_object_domain (tb);
12762 klass = mono_class_from_mono_type (tb->type.type);
12765 * Check for user defined Type subclasses.
12767 RESOLVE_TYPE (tb->parent, &error);
12768 mono_error_raise_exception (&error); /* FIXME don't raise here */
12769 check_array_for_usertypes (tb->interfaces, &error);
12770 mono_error_raise_exception (&error); /*FIXME don't raise here */
12772 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12773 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12775 RESOLVE_TYPE (fb->type, &error);
12776 mono_error_raise_exception (&error); /* FIXME don't raise here */
12777 check_array_for_usertypes (fb->modreq, &error);
12778 mono_error_raise_exception (&error); /*FIXME don't raise here */
12779 check_array_for_usertypes (fb->modopt, &error);
12780 mono_error_raise_exception (&error); /*FIXME don't raise here */
12781 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12782 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12783 mono_error_raise_exception (&error); /* FIXME don't raise here */
12789 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12790 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12792 RESOLVE_TYPE (mb->rtype, &error);
12793 mono_error_raise_exception (&error); /* FIXME don't raise here */
12794 check_array_for_usertypes (mb->return_modreq, &error);
12795 mono_error_raise_exception (&error); /*FIXME don't raise here */
12796 check_array_for_usertypes (mb->return_modopt, &error);
12797 mono_error_raise_exception (&error); /*FIXME don't raise here */
12798 check_array_for_usertypes (mb->parameters, &error);
12799 mono_error_raise_exception (&error); /*FIXME don't raise here */
12800 if (mb->param_modreq)
12801 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12802 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12803 mono_error_raise_exception (&error); /*FIXME don't raise here */
12805 if (mb->param_modopt)
12806 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12807 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12808 mono_error_raise_exception (&error); /*FIXME don't raise here */
12814 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12815 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
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 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12836 * we need to lock the domain because the lock will be taken inside
12837 * So, we need to keep the locking order correct.
12839 mono_loader_lock ();
12840 mono_domain_lock (domain);
12841 if (klass->wastypebuilder) {
12842 mono_domain_unlock (domain);
12843 mono_loader_unlock ();
12845 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12846 mono_error_raise_exception (&error); /* FIXME don't raise here */
12851 * Fields to set in klass:
12852 * the various flags: delegate/unicode/contextbound etc.
12854 klass->flags = tb->attrs;
12855 klass->has_cctor = 1;
12856 klass->has_finalize = 1;
12857 klass->has_finalize_inited = 1;
12859 mono_class_setup_parent (klass, klass->parent);
12860 /* fool mono_class_setup_supertypes */
12861 klass->supertypes = NULL;
12862 mono_class_setup_supertypes (klass);
12863 mono_class_setup_mono_type (klass);
12866 if (!((MonoDynamicImage*)klass->image)->run) {
12867 if (klass->generic_container) {
12868 /* FIXME: The code below can't handle generic classes */
12869 klass->wastypebuilder = TRUE;
12870 mono_loader_unlock ();
12871 mono_domain_unlock (domain);
12873 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12874 mono_error_raise_exception (&error); /* FIXME don't raise here */
12881 /* enums are done right away */
12882 if (!klass->enumtype)
12883 if (!ensure_runtime_vtable (klass, &error))
12886 if (tb->subtypes) {
12887 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12888 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12889 mono_class_alloc_ext (klass);
12890 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12891 if (!is_ok (&error)) goto failure;
12892 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12896 klass->nested_classes_inited = TRUE;
12898 /* fields and object layout */
12899 if (klass->parent) {
12900 if (!klass->parent->size_inited)
12901 mono_class_init (klass->parent);
12902 klass->instance_size = klass->parent->instance_size;
12903 klass->sizes.class_size = 0;
12904 klass->min_align = klass->parent->min_align;
12905 /* if the type has no fields we won't call the field_setup
12906 * routine which sets up klass->has_references.
12908 klass->has_references |= klass->parent->has_references;
12910 klass->instance_size = sizeof (MonoObject);
12911 klass->min_align = 1;
12914 /* FIXME: handle packing_size and instance_size */
12915 typebuilder_setup_fields (klass, &error);
12916 if (!mono_error_ok (&error))
12918 typebuilder_setup_properties (klass, &error);
12919 if (!mono_error_ok (&error))
12922 typebuilder_setup_events (klass, &error);
12923 if (!mono_error_ok (&error))
12926 klass->wastypebuilder = TRUE;
12929 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12930 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12931 * we want to return normal System.MonoType objects, so clear these out from the cache.
12933 * Together with this we must ensure the contents of all instances to match the created type.
12935 if (domain->type_hash && klass->generic_container)
12936 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12938 mono_domain_unlock (domain);
12939 mono_loader_unlock ();
12941 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12942 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12943 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12946 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12947 mono_error_raise_exception (&error); /* FIXME don't raise here */
12949 g_assert (res != (MonoReflectionType*)tb);
12954 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12955 klass->wastypebuilder = TRUE;
12956 mono_domain_unlock (domain);
12957 mono_loader_unlock ();
12958 mono_error_raise_exception (&error);
12963 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12965 MonoGenericParamFull *param;
12970 image = &gparam->tbuilder->module->dynamic_image->image;
12972 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12974 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12975 g_assert (mono_error_ok (&error));
12976 param->param.num = gparam->index;
12978 if (gparam->mbuilder) {
12979 if (!gparam->mbuilder->generic_container) {
12980 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12981 mono_error_raise_exception (&error); /* FIXME don't raise here */
12983 MonoClass *klass = mono_class_from_mono_type (tb);
12984 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12985 gparam->mbuilder->generic_container->is_method = TRUE;
12987 * Cannot set owner.method, since the MonoMethod is not created yet.
12988 * Set the image field instead, so type_in_image () works.
12990 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12991 gparam->mbuilder->generic_container->owner.image = klass->image;
12993 param->param.owner = gparam->mbuilder->generic_container;
12994 } else if (gparam->tbuilder) {
12995 if (!gparam->tbuilder->generic_container) {
12996 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12997 mono_error_raise_exception (&error); /* FIXME don't raise here */
12998 MonoClass *klass = mono_class_from_mono_type (tb);
12999 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13000 gparam->tbuilder->generic_container->owner.klass = klass;
13002 param->param.owner = gparam->tbuilder->generic_container;
13005 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13007 gparam->type.type = &pklass->byval_arg;
13009 mono_class_set_ref_info (pklass, gparam);
13010 mono_image_append_class_to_reflection_info_set (pklass);
13014 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13017 MonoReflectionModuleBuilder *module = sig->module;
13018 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13019 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13024 check_array_for_usertypes (sig->arguments, &error);
13025 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13027 sigbuffer_init (&buf, 32);
13029 sigbuffer_add_value (&buf, 0x07);
13030 sigbuffer_add_value (&buf, na);
13031 if (assembly != NULL){
13032 for (i = 0; i < na; ++i) {
13033 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13034 encode_reflection_type (assembly, type, &buf, &error);
13035 if (!is_ok (&error)) goto fail;
13039 buflen = buf.p - buf.buf;
13040 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13041 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13042 sigbuffer_free (&buf);
13045 sigbuffer_free (&buf);
13046 mono_error_raise_exception (&error); /* FIXME don't raise here */
13051 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13054 MonoDynamicImage *assembly = sig->module->dynamic_image;
13055 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13060 check_array_for_usertypes (sig->arguments, &error);
13061 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13063 sigbuffer_init (&buf, 32);
13065 sigbuffer_add_value (&buf, 0x06);
13066 for (i = 0; i < na; ++i) {
13067 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13068 encode_reflection_type (assembly, type, &buf, &error);
13069 if (!is_ok (&error))
13073 buflen = buf.p - buf.buf;
13074 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13075 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13076 sigbuffer_free (&buf);
13080 sigbuffer_free (&buf);
13081 mono_error_raise_exception (&error); /* FIXME don't raise here */
13086 MonoMethod *handle;
13087 MonoDomain *domain;
13088 } DynamicMethodReleaseData;
13091 * The runtime automatically clean up those after finalization.
13093 static MonoReferenceQueue *dynamic_method_queue;
13096 free_dynamic_method (void *dynamic_method)
13098 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13099 MonoDomain *domain = data->domain;
13100 MonoMethod *method = data->handle;
13103 mono_domain_lock (domain);
13104 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13105 g_hash_table_remove (domain->method_to_dyn_method, method);
13106 mono_domain_unlock (domain);
13107 g_assert (dis_link);
13108 mono_gchandle_free (dis_link);
13110 mono_runtime_free_method (domain, method);
13115 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13118 MonoReferenceQueue *queue;
13119 MonoMethod *handle;
13120 DynamicMethodReleaseData *release_data;
13121 ReflectionMethodBuilder rmb;
13122 MonoMethodSignature *sig;
13124 MonoDomain *domain;
13128 if (mono_runtime_is_shutting_down ())
13129 mono_raise_exception (mono_get_exception_invalid_operation (""));
13131 if (!(queue = dynamic_method_queue)) {
13132 mono_loader_lock ();
13133 if (!(queue = dynamic_method_queue))
13134 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13135 mono_loader_unlock ();
13138 sig = dynamic_method_to_signature (mb);
13140 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13143 * Resolve references.
13146 * Every second entry in the refs array is reserved for storing handle_class,
13147 * which is needed by the ldtoken implementation in the JIT.
13149 rmb.nrefs = mb->nrefs;
13150 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13151 for (i = 0; i < mb->nrefs; i += 2) {
13152 MonoClass *handle_class;
13154 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13156 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13157 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13159 * The referenced DynamicMethod should already be created by the managed
13160 * code, except in the case of circular references. In that case, we store
13161 * method in the refs array, and fix it up later when the referenced
13162 * DynamicMethod is created.
13164 if (method->mhandle) {
13165 ref = method->mhandle;
13167 /* FIXME: GC object stored in unmanaged memory */
13170 /* FIXME: GC object stored in unmanaged memory */
13171 method->referenced_by = g_slist_append (method->referenced_by, mb);
13173 handle_class = mono_defaults.methodhandle_class;
13175 MonoException *ex = NULL;
13176 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13178 ex = mono_get_exception_type_load (NULL, NULL);
13179 else if (mono_security_core_clr_enabled ())
13180 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13184 mono_raise_exception (ex);
13189 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13190 rmb.refs [i + 1] = handle_class;
13194 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13195 if (!is_ok (&error)) {
13197 mono_error_raise_exception (&error); /* FIXME don't raise here */
13199 klass = mono_class_from_mono_type (owner_type);
13201 klass = mono_defaults.object_class;
13204 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13205 release_data = g_new (DynamicMethodReleaseData, 1);
13206 release_data->handle = handle;
13207 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13208 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13209 g_free (release_data);
13211 /* Fix up refs entries pointing at us */
13212 for (l = mb->referenced_by; l; l = l->next) {
13213 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13214 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13217 g_assert (method->mhandle);
13219 data = (gpointer*)wrapper->method_data;
13220 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13221 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13222 data [i + 1] = mb->mhandle;
13225 g_slist_free (mb->referenced_by);
13229 /* ilgen is no longer needed */
13232 domain = mono_domain_get ();
13233 mono_domain_lock (domain);
13234 if (!domain->method_to_dyn_method)
13235 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13236 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13237 mono_domain_unlock (domain);
13240 #endif /* DISABLE_REFLECTION_EMIT */
13244 * mono_reflection_is_valid_dynamic_token:
13246 * Returns TRUE if token is valid.
13250 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13252 return lookup_dyn_token (image, token) != NULL;
13255 MonoMethodSignature *
13256 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13258 MonoMethodSignature *sig;
13259 g_assert (image_is_dynamic (image));
13261 mono_error_init (error);
13263 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13267 return mono_method_signature_checked (method, error);
13270 #ifndef DISABLE_REFLECTION_EMIT
13273 * mono_reflection_lookup_dynamic_token:
13275 * Finish the Builder object pointed to by TOKEN and return the corresponding
13276 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13277 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13280 * LOCKING: Take the loader lock
13283 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13285 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13289 obj = lookup_dyn_token (assembly, token);
13292 g_error ("Could not find required dynamic token 0x%08x", token);
13298 handle_class = &klass;
13299 return resolve_object (image, obj, handle_class, context);
13303 * ensure_complete_type:
13305 * Ensure that KLASS is completed if it is a dynamic type, or references
13309 ensure_complete_type (MonoClass *klass)
13313 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13314 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13316 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13317 mono_error_raise_exception (&error); /* FIXME don't raise here */
13319 // Asserting here could break a lot of code
13320 //g_assert (klass->wastypebuilder);
13323 if (klass->generic_class) {
13324 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13327 for (i = 0; i < inst->type_argc; ++i) {
13328 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13334 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13337 gpointer result = NULL;
13339 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13340 result = mono_string_intern_checked ((MonoString*)obj, &error);
13341 mono_error_raise_exception (&error); /* FIXME don't raise here */
13342 *handle_class = mono_defaults.string_class;
13344 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13345 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13346 mono_error_raise_exception (&error); /* FIXME don't raise here */
13347 MonoClass *mc = mono_class_from_mono_type (type);
13348 if (!mono_class_init (mc))
13349 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13352 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13353 mono_error_raise_exception (&error); /* FIXME don't raise here */
13355 result = mono_class_from_mono_type (inflated);
13356 mono_metadata_free_type (inflated);
13358 result = mono_class_from_mono_type (type);
13360 *handle_class = mono_defaults.typehandle_class;
13362 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13363 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13364 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13365 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13366 result = ((MonoReflectionMethod*)obj)->method;
13369 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13370 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13372 *handle_class = mono_defaults.methodhandle_class;
13374 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13375 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13376 result = mb->mhandle;
13378 /* Type is not yet created */
13379 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13381 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13382 mono_error_raise_exception (&error); /* FIXME don't raise here */
13385 * Hopefully this has been filled in by calling CreateType() on the
13389 * TODO: This won't work if the application finishes another
13390 * TypeBuilder instance instead of this one.
13392 result = mb->mhandle;
13396 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13397 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13399 *handle_class = mono_defaults.methodhandle_class;
13400 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13401 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13403 result = cb->mhandle;
13405 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13407 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13408 mono_error_raise_exception (&error); /* FIXME don't raise here */
13409 result = cb->mhandle;
13413 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13414 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13416 *handle_class = mono_defaults.methodhandle_class;
13417 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13418 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13420 ensure_complete_type (field->parent);
13422 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13423 mono_error_raise_exception (&error); /* FIXME don't raise here */
13425 MonoClass *klass = mono_class_from_mono_type (inflated);
13426 MonoClassField *inflated_field;
13427 gpointer iter = NULL;
13428 mono_metadata_free_type (inflated);
13429 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13430 if (!strcmp (field->name, inflated_field->name))
13433 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13434 result = inflated_field;
13438 *handle_class = mono_defaults.fieldhandle_class;
13440 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13441 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13442 result = fb->handle;
13445 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13447 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13448 mono_error_raise_exception (&error); /* FIXME don't raise here */
13449 result = fb->handle;
13452 if (fb->handle && fb->handle->parent->generic_container) {
13453 MonoClass *klass = fb->handle->parent;
13454 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13455 mono_error_raise_exception (&error); /* FIXME don't raise here */
13457 MonoClass *inflated = mono_class_from_mono_type (type);
13459 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13461 mono_metadata_free_type (type);
13463 *handle_class = mono_defaults.fieldhandle_class;
13464 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13465 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13466 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13467 mono_error_raise_exception (&error); /* FIXME don't raise here */
13470 klass = type->data.klass;
13471 if (klass->wastypebuilder) {
13472 /* Already created */
13476 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13477 mono_error_raise_exception (&error); /* FIXME don't raise here */
13478 result = type->data.klass;
13481 *handle_class = mono_defaults.typehandle_class;
13482 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13483 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13484 MonoMethodSignature *sig;
13487 if (helper->arguments)
13488 nargs = mono_array_length (helper->arguments);
13492 sig = mono_metadata_signature_alloc (image, nargs);
13493 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13494 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13496 if (helper->unmanaged_call_conv) { /* unmanaged */
13497 sig->call_convention = helper->unmanaged_call_conv - 1;
13498 sig->pinvoke = TRUE;
13499 } else if (helper->call_conv & 0x02) {
13500 sig->call_convention = MONO_CALL_VARARG;
13502 sig->call_convention = MONO_CALL_DEFAULT;
13505 sig->param_count = nargs;
13506 /* TODO: Copy type ? */
13507 sig->ret = helper->return_type->type;
13508 for (i = 0; i < nargs; ++i) {
13509 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13510 mono_error_raise_exception (&error); /* FIXME don't raise here */
13514 *handle_class = NULL;
13515 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13516 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13517 /* Already created by the managed code */
13518 g_assert (method->mhandle);
13519 result = method->mhandle;
13520 *handle_class = mono_defaults.methodhandle_class;
13521 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13522 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13523 mono_error_raise_exception (&error); /* FIXME don't raise here */
13524 type = mono_class_inflate_generic_type_checked (type, context, &error);
13525 mono_error_raise_exception (&error); /* FIXME don't raise here */
13527 result = mono_class_from_mono_type (type);
13528 *handle_class = mono_defaults.typehandle_class;
13530 mono_metadata_free_type (type);
13531 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13532 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13533 mono_error_raise_exception (&error); /* FIXME don't raise here */
13534 type = mono_class_inflate_generic_type_checked (type, context, &error);
13535 mono_error_raise_exception (&error); /* FIXME don't raise here */
13537 result = mono_class_from_mono_type (type);
13538 *handle_class = mono_defaults.typehandle_class;
13540 mono_metadata_free_type (type);
13541 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13542 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13543 MonoClass *inflated;
13545 MonoClassField *field;
13547 if (is_sre_field_builder (mono_object_class (f->fb)))
13548 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13549 else if (is_sr_mono_field (mono_object_class (f->fb)))
13550 field = ((MonoReflectionField*)f->fb)->field;
13552 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)));
13554 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13555 mono_error_raise_exception (&error); /* FIXME don't raise here */
13556 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13557 mono_error_raise_exception (&error); /* FIXME don't raise here */
13559 inflated = mono_class_from_mono_type (type);
13561 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13562 ensure_complete_type (field->parent);
13564 mono_metadata_free_type (type);
13565 *handle_class = mono_defaults.fieldhandle_class;
13566 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13567 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13568 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13569 mono_error_raise_exception (&error); /* FIXME don't raise here */
13570 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13571 mono_error_raise_exception (&error); /* FIXME don't raise here */
13573 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13574 MonoMethod *method;
13576 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13577 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13578 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13579 method = ((MonoReflectionMethod *)c->cb)->method;
13581 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)));
13583 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13584 *handle_class = mono_defaults.methodhandle_class;
13585 mono_metadata_free_type (type);
13586 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13587 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13588 if (m->method_args) {
13589 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13590 mono_error_raise_exception (&error); /* FIXME don't raise here */
13592 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13593 mono_error_assert_ok (&error);
13596 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13597 mono_error_raise_exception (&error); /* FIXME don't raise here */
13598 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13599 mono_error_raise_exception (&error); /* FIXME don't raise here */
13601 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13602 MonoMethod *method;
13604 if (is_sre_method_builder (mono_object_class (m->mb)))
13605 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13606 else if (is_sr_mono_method (mono_object_class (m->mb)))
13607 method = ((MonoReflectionMethod *)m->mb)->method;
13609 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)));
13611 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13612 mono_metadata_free_type (type);
13614 *handle_class = mono_defaults.methodhandle_class;
13615 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13616 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13619 MonoMethod *method;
13623 mtype = mono_reflection_type_get_handle (m->parent, &error);
13624 mono_error_raise_exception (&error); /* FIXME don't raise here */
13625 klass = mono_class_from_mono_type (mtype);
13627 /* Find the method */
13629 name = mono_string_to_utf8 (m->name);
13631 while ((method = mono_class_get_methods (klass, &iter))) {
13632 if (!strcmp (method->name, name))
13639 // FIXME: Check parameters/return value etc. match
13642 *handle_class = mono_defaults.methodhandle_class;
13643 } else if (is_sre_array (mono_object_get_class(obj)) ||
13644 is_sre_byref (mono_object_get_class(obj)) ||
13645 is_sre_pointer (mono_object_get_class(obj))) {
13646 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13647 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13648 mono_error_raise_exception (&error); /* FIXME don't raise here */
13651 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13652 mono_error_raise_exception (&error); /* FIXME don't raise here */
13654 result = mono_class_from_mono_type (inflated);
13655 mono_metadata_free_type (inflated);
13657 result = mono_class_from_mono_type (type);
13659 *handle_class = mono_defaults.typehandle_class;
13661 g_print ("%s\n", obj->vtable->klass->name);
13662 g_assert_not_reached ();
13667 #else /* DISABLE_REFLECTION_EMIT */
13670 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13672 g_assert_not_reached ();
13677 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13679 g_assert_not_reached ();
13683 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13685 g_assert_not_reached ();
13689 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13691 g_assert_not_reached ();
13695 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13697 g_assert_not_reached ();
13701 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13703 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13707 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13709 g_assert_not_reached ();
13713 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13715 g_assert_not_reached ();
13718 MonoReflectionModule *
13719 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13721 g_assert_not_reached ();
13726 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13728 g_assert_not_reached ();
13733 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13735 g_assert_not_reached ();
13740 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13741 gboolean create_open_instance, gboolean register_token, MonoError *error)
13743 g_assert_not_reached ();
13748 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13753 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13755 g_assert_not_reached ();
13759 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13762 *num_overrides = 0;
13765 MonoReflectionEvent *
13766 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13768 g_assert_not_reached ();
13772 MonoReflectionType*
13773 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13775 g_assert_not_reached ();
13780 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13782 g_assert_not_reached ();
13786 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13788 g_assert_not_reached ();
13793 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13795 g_assert_not_reached ();
13800 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13805 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13811 mono_reflection_type_get_handle (MonoReflectionType* ref)
13819 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13821 g_assert_not_reached ();
13824 #endif /* DISABLE_REFLECTION_EMIT */
13826 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13827 const static guint32 declsec_flags_map[] = {
13828 0x00000000, /* empty */
13829 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13830 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13831 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13832 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13833 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13834 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13835 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13836 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13837 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13838 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13839 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13840 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13841 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13842 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13843 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13844 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13845 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13846 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13850 * Returns flags that includes all available security action associated to the handle.
13851 * @token: metadata token (either for a class or a method)
13852 * @image: image where resides the metadata.
13855 mono_declsec_get_flags (MonoImage *image, guint32 token)
13857 int index = mono_metadata_declsec_from_index (image, token);
13858 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13859 guint32 result = 0;
13863 /* HasSecurity can be present for other, not specially encoded, attributes,
13864 e.g. SuppressUnmanagedCodeSecurityAttribute */
13868 for (i = index; i < t->rows; i++) {
13869 guint32 cols [MONO_DECL_SECURITY_SIZE];
13871 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13872 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13875 action = cols [MONO_DECL_SECURITY_ACTION];
13876 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13877 result |= declsec_flags_map [action];
13879 g_assert_not_reached ();
13886 * Get the security actions (in the form of flags) associated with the specified method.
13888 * @method: The method for which we want the declarative security flags.
13889 * Return the declarative security flags for the method (only).
13891 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13892 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13895 mono_declsec_flags_from_method (MonoMethod *method)
13897 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13898 /* FIXME: No cache (for the moment) */
13899 guint32 idx = mono_method_get_index (method);
13900 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13901 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13902 return mono_declsec_get_flags (method->klass->image, idx);
13908 * Get the security actions (in the form of flags) associated with the specified class.
13910 * @klass: The class for which we want the declarative security flags.
13911 * Return the declarative security flags for the class.
13913 * Note: We cache the flags inside the MonoClass structure as this will get
13914 * called very often (at least for each method).
13917 mono_declsec_flags_from_class (MonoClass *klass)
13919 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13920 if (!klass->ext || !klass->ext->declsec_flags) {
13923 idx = mono_metadata_token_index (klass->type_token);
13924 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13925 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13926 mono_loader_lock ();
13927 mono_class_alloc_ext (klass);
13928 mono_loader_unlock ();
13929 /* we cache the flags on classes */
13930 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13932 return klass->ext->declsec_flags;
13938 * Get the security actions (in the form of flags) associated with the specified assembly.
13940 * @assembly: The assembly for which we want the declarative security flags.
13941 * Return the declarative security flags for the assembly.
13944 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13946 guint32 idx = 1; /* there is only one assembly */
13947 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13948 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13949 return mono_declsec_get_flags (assembly->image, idx);
13954 * Fill actions for the specific index (which may either be an encoded class token or
13955 * an encoded method token) from the metadata image.
13956 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13959 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13960 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13962 MonoBoolean result = FALSE;
13964 guint32 cols [MONO_DECL_SECURITY_SIZE];
13965 int index = mono_metadata_declsec_from_index (image, token);
13968 t = &image->tables [MONO_TABLE_DECLSECURITY];
13969 for (i = index; i < t->rows; i++) {
13970 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13972 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13975 /* if present only replace (class) permissions with method permissions */
13976 /* if empty accept either class or method permissions */
13977 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13978 if (!actions->demand.blob) {
13979 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13980 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13981 actions->demand.blob = (char*) (blob + 2);
13982 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13985 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13986 if (!actions->noncasdemand.blob) {
13987 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13988 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13989 actions->noncasdemand.blob = (char*) (blob + 2);
13990 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13993 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13994 if (!actions->demandchoice.blob) {
13995 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13996 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13997 actions->demandchoice.blob = (char*) (blob + 2);
13998 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14008 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14009 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14011 guint32 idx = mono_metadata_token_index (klass->type_token);
14012 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14013 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14014 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14018 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14019 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14021 guint32 idx = mono_method_get_index (method);
14022 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14023 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14024 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14028 * Collect all actions (that requires to generate code in mini) assigned for
14029 * the specified method.
14030 * Note: Don't use the content of actions if the function return FALSE.
14033 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14035 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14036 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14037 MonoBoolean result = FALSE;
14040 /* quick exit if no declarative security is present in the metadata */
14041 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14044 /* we want the original as the wrapper is "free" of the security informations */
14045 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14046 method = mono_marshal_method_from_wrapper (method);
14051 /* First we look for method-level attributes */
14052 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14053 mono_class_init (method->klass);
14054 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14056 result = mono_declsec_get_method_demands_params (method, demands,
14057 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14060 /* Here we use (or create) the class declarative cache to look for demands */
14061 flags = mono_declsec_flags_from_class (method->klass);
14062 if (flags & mask) {
14064 mono_class_init (method->klass);
14065 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14067 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14068 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14071 /* The boolean return value is used as a shortcut in case nothing needs to
14072 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14078 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14080 * Note: Don't use the content of actions if the function return FALSE.
14083 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14085 MonoBoolean result = FALSE;
14088 /* quick exit if no declarative security is present in the metadata */
14089 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14092 /* we want the original as the wrapper is "free" of the security informations */
14093 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14094 method = mono_marshal_method_from_wrapper (method);
14099 /* results are independant - zeroize both */
14100 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14101 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14103 /* First we look for method-level attributes */
14104 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14105 mono_class_init (method->klass);
14107 result = mono_declsec_get_method_demands_params (method, cmethod,
14108 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14111 /* Here we use (or create) the class declarative cache to look for demands */
14112 flags = mono_declsec_flags_from_class (method->klass);
14113 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14114 mono_class_init (method->klass);
14116 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14117 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14124 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14126 * @klass The inherited class - this is the class that provides the security check (attributes)
14128 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14130 * Note: Don't use the content of actions if the function return FALSE.
14133 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14135 MonoBoolean result = FALSE;
14138 /* quick exit if no declarative security is present in the metadata */
14139 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14142 /* Here we use (or create) the class declarative cache to look for demands */
14143 flags = mono_declsec_flags_from_class (klass);
14144 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14145 mono_class_init (klass);
14146 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14148 result |= mono_declsec_get_class_demands_params (klass, demands,
14149 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14156 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14158 * Note: Don't use the content of actions if the function return FALSE.
14161 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14163 /* quick exit if no declarative security is present in the metadata */
14164 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14167 /* we want the original as the wrapper is "free" of the security informations */
14168 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14169 method = mono_marshal_method_from_wrapper (method);
14174 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14175 mono_class_init (method->klass);
14176 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14178 return mono_declsec_get_method_demands_params (method, demands,
14179 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14186 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14188 guint32 cols [MONO_DECL_SECURITY_SIZE];
14192 int index = mono_metadata_declsec_from_index (image, token);
14196 t = &image->tables [MONO_TABLE_DECLSECURITY];
14197 for (i = index; i < t->rows; i++) {
14198 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14200 /* shortcut - index are ordered */
14201 if (token != cols [MONO_DECL_SECURITY_PARENT])
14204 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14205 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14206 entry->blob = (char*) (metadata + 2);
14207 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14216 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14218 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14219 guint32 idx = mono_method_get_index (method);
14220 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14221 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14222 return get_declsec_action (method->klass->image, idx, action, entry);
14228 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14231 guint32 flags = mono_declsec_flags_from_class (klass);
14232 if (declsec_flags_map [action] & flags) {
14233 guint32 idx = mono_metadata_token_index (klass->type_token);
14234 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14235 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14236 return get_declsec_action (klass->image, idx, action, entry);
14242 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14244 guint32 idx = 1; /* there is only one assembly */
14245 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14246 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14248 return get_declsec_action (assembly->image, idx, action, entry);
14252 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14255 MonoObject *res, *exc;
14257 static MonoMethod *method = NULL;
14259 if (method == NULL) {
14260 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14265 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14266 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14268 g_assert (mono_class_get_ref_info (klass));
14269 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14271 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14272 mono_error_raise_exception (&error); /* FIXME don't raise here */
14274 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14276 if (exc || !mono_error_ok (&error)) {
14277 mono_error_cleanup (&error);
14280 return *(MonoBoolean*)mono_object_unbox (res);
14284 * mono_reflection_type_get_type:
14285 * @reftype: the System.Type object
14287 * Returns the MonoType* associated with the C# System.Type object @reftype.
14290 mono_reflection_type_get_type (MonoReflectionType *reftype)
14292 g_assert (reftype);
14295 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14296 mono_error_assert_ok (&error);
14301 * mono_reflection_assembly_get_assembly:
14302 * @refassembly: the System.Reflection.Assembly object
14304 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14307 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14309 g_assert (refassembly);
14311 return refassembly->assembly;