2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
247 dynamic_images_lock (void)
249 mono_os_mutex_lock (&dynamic_images_mutex);
253 dynamic_images_unlock (void)
255 mono_os_mutex_unlock (&dynamic_images_mutex);
259 * mono_find_dynamic_image_owner:
261 * Find the dynamic image, if any, which a given pointer is located in the memory of.
264 mono_find_dynamic_image_owner (void *ptr)
266 MonoImage *owner = NULL;
269 dynamic_images_lock ();
273 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275 if (mono_mempool_contains_addr (image->mempool, ptr))
280 dynamic_images_unlock ();
286 mono_reflection_init (void)
288 mono_os_mutex_init (&dynamic_images_mutex);
292 dynamic_image_lock (MonoDynamicImage *image)
294 MONO_PREPARE_BLOCKING;
295 mono_image_lock ((MonoImage*)image);
296 MONO_FINISH_BLOCKING;
300 dynamic_image_unlock (MonoDynamicImage *image)
302 mono_image_unlock ((MonoImage*)image);
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
308 MONO_REQ_GC_UNSAFE_MODE;
310 dynamic_image_lock (assembly);
311 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312 dynamic_image_unlock (assembly);
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
318 MONO_REQ_GC_UNSAFE_MODE;
322 dynamic_image_lock (assembly);
323 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324 dynamic_image_unlock (assembly);
330 sigbuffer_init (SigBuffer *buf, int size)
332 MONO_REQ_GC_NEUTRAL_MODE;
334 buf->buf = (char *)g_malloc (size);
336 buf->end = buf->buf + size;
340 sigbuffer_make_room (SigBuffer *buf, int size)
342 MONO_REQ_GC_NEUTRAL_MODE;
344 if (buf->end - buf->p < size) {
345 int new_size = buf->end - buf->buf + size + 32;
346 char *p = (char *)g_realloc (buf->buf, new_size);
347 size = buf->p - buf->buf;
350 buf->end = buf->buf + new_size;
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
357 MONO_REQ_GC_NEUTRAL_MODE;
359 sigbuffer_make_room (buf, 6);
360 mono_metadata_encode_value (val, buf->p, &buf->p);
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
366 MONO_REQ_GC_NEUTRAL_MODE;
368 sigbuffer_make_room (buf, 1);
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
376 MONO_REQ_GC_NEUTRAL_MODE;
378 sigbuffer_make_room (buf, size);
379 memcpy (buf->p, p, size);
384 sigbuffer_free (SigBuffer *buf)
386 MONO_REQ_GC_NEUTRAL_MODE;
391 #ifndef DISABLE_REFLECTION_EMIT
395 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399 image_g_malloc (MonoImage *image, guint size)
401 MONO_REQ_GC_NEUTRAL_MODE;
404 return mono_image_alloc (image, size);
406 return g_malloc (size);
408 #endif /* !DISABLE_REFLECTION_EMIT */
413 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417 image_g_malloc0 (MonoImage *image, guint size)
419 MONO_REQ_GC_NEUTRAL_MODE;
422 return mono_image_alloc0 (image, size);
424 return g_malloc0 (size);
429 * @image: a MonoImage
432 * If @image is NULL, free @ptr, otherwise do nothing.
435 image_g_free (MonoImage *image, gpointer ptr)
441 #ifndef DISABLE_REFLECTION_EMIT
443 image_strdup (MonoImage *image, const char *s)
445 MONO_REQ_GC_NEUTRAL_MODE;
448 return mono_image_strdup (image, s);
454 #define image_g_new(image,struct_type, n_structs) \
455 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
457 #define image_g_new0(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
462 alloc_table (MonoDynamicTable *table, guint nrows)
464 MONO_REQ_GC_NEUTRAL_MODE;
467 g_assert (table->columns);
468 if (nrows + 1 >= table->alloc_rows) {
469 while (nrows + 1 >= table->alloc_rows) {
470 if (table->alloc_rows == 0)
471 table->alloc_rows = 16;
473 table->alloc_rows *= 2;
476 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
481 make_room_in_stream (MonoDynamicStream *stream, int size)
483 MONO_REQ_GC_NEUTRAL_MODE;
485 if (size <= stream->alloc_size)
488 while (stream->alloc_size <= size) {
489 if (stream->alloc_size < 4096)
490 stream->alloc_size = 4096;
492 stream->alloc_size *= 2;
495 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
501 MONO_REQ_GC_NEUTRAL_MODE;
505 gpointer oldkey, oldval;
507 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508 return GPOINTER_TO_UINT (oldval);
510 len = strlen (str) + 1;
513 make_room_in_stream (sh, idx + len);
516 * We strdup the string even if we already copy them in sh->data
517 * so that the string pointers in the hash remain valid even if
518 * we need to realloc sh->data. We may want to avoid that later.
520 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521 memcpy (sh->data + idx, str, len);
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
529 MONO_REQ_GC_UNSAFE_MODE;
531 char *name = mono_string_to_utf8 (str);
533 idx = string_heap_insert (sh, name);
538 #ifndef DISABLE_REFLECTION_EMIT
540 string_heap_init (MonoDynamicStream *sh)
542 MONO_REQ_GC_NEUTRAL_MODE;
545 sh->alloc_size = 4096;
546 sh->data = (char *)g_malloc (4096);
547 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548 string_heap_insert (sh, "");
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
555 MONO_REQ_GC_NEUTRAL_MODE;
559 make_room_in_stream (stream, stream->index + len);
560 memcpy (stream->data + stream->index, data, len);
562 stream->index += len;
564 * align index? Not without adding an additional param that controls it since
565 * we may store a blob value in pieces.
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
573 MONO_REQ_GC_NEUTRAL_MODE;
577 make_room_in_stream (stream, stream->index + len);
578 memset (stream->data + stream->index, 0, len);
580 stream->index += len;
585 stream_data_align (MonoDynamicStream *stream)
587 MONO_REQ_GC_NEUTRAL_MODE;
590 guint32 count = stream->index % 4;
592 /* we assume the stream data will be aligned */
594 mono_image_add_stream_data (stream, buf, 4 - count);
597 #ifndef DISABLE_REFLECTION_EMIT
599 mono_blob_entry_hash (const char* str)
601 MONO_REQ_GC_NEUTRAL_MODE;
605 len = mono_metadata_decode_blob_size (str, &str);
609 for (str += 1; str < end; str++)
610 h = (h << 5) - h + *str;
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619 MONO_REQ_GC_NEUTRAL_MODE;
624 len = mono_metadata_decode_blob_size (str1, &end1);
625 len2 = mono_metadata_decode_blob_size (str2, &end2);
628 return memcmp (end1, end2, len) == 0;
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
634 MONO_REQ_GC_NEUTRAL_MODE;
638 gpointer oldkey, oldval;
640 copy = (char *)g_malloc (s1+s2);
641 memcpy (copy, b1, s1);
642 memcpy (copy + s1, b2, s2);
643 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
645 idx = GPOINTER_TO_UINT (oldval);
647 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648 mono_image_add_stream_data (&assembly->blob, b2, s2);
649 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
657 MONO_REQ_GC_NEUTRAL_MODE;
661 guint32 size = buf->p - buf->buf;
663 g_assert (size <= (buf->end - buf->buf));
664 mono_metadata_encode_value (size, b, &b);
665 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
669 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670 * dest may be misaligned.
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674 MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
678 for (elem = 0; elem < nelem; ++elem) {
704 g_assert_not_reached ();
710 memcpy (dest, val, len * nelem);
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
717 MONO_REQ_GC_UNSAFE_MODE;
721 guint32 idx = 0, len;
723 len = str->length * 2;
724 mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
727 char *swapped = g_malloc (2 * mono_string_length (str));
728 const char *p = (const char*)mono_string_chars (str);
730 swap_with_size (swapped, p, 2, mono_string_length (str));
731 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
735 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
740 #ifndef DISABLE_REFLECTION_EMIT
742 default_class_from_mono_type (MonoType *type)
744 MONO_REQ_GC_NEUTRAL_MODE;
746 switch (type->type) {
747 case MONO_TYPE_OBJECT:
748 return mono_defaults.object_class;
750 return mono_defaults.void_class;
751 case MONO_TYPE_BOOLEAN:
752 return mono_defaults.boolean_class;
754 return mono_defaults.char_class;
756 return mono_defaults.sbyte_class;
758 return mono_defaults.byte_class;
760 return mono_defaults.int16_class;
762 return mono_defaults.uint16_class;
764 return mono_defaults.int32_class;
766 return mono_defaults.uint32_class;
768 return mono_defaults.int_class;
770 return mono_defaults.uint_class;
772 return mono_defaults.int64_class;
774 return mono_defaults.uint64_class;
776 return mono_defaults.single_class;
778 return mono_defaults.double_class;
779 case MONO_TYPE_STRING:
780 return mono_defaults.string_class;
782 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783 g_assert_not_reached ();
791 * mono_class_get_ref_info:
793 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
796 mono_class_get_ref_info (MonoClass *klass)
798 MONO_REQ_GC_UNSAFE_MODE;
800 if (klass->ref_info_handle == 0)
803 return mono_gchandle_get_target (klass->ref_info_handle);
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
809 MONO_REQ_GC_UNSAFE_MODE;
811 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812 g_assert (klass->ref_info_handle != 0);
816 mono_class_free_ref_info (MonoClass *klass)
818 MONO_REQ_GC_NEUTRAL_MODE;
820 if (klass->ref_info_handle) {
821 mono_gchandle_free (klass->ref_info_handle);
822 klass->ref_info_handle = 0;
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
829 MONO_REQ_GC_NEUTRAL_MODE;
832 MonoGenericInst *class_inst;
837 class_inst = gclass->context.class_inst;
839 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840 klass = gclass->container_class;
841 sigbuffer_add_value (buf, klass->byval_arg.type);
842 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
844 sigbuffer_add_value (buf, class_inst->type_argc);
845 for (i = 0; i < class_inst->type_argc; ++i)
846 encode_type (assembly, class_inst->type_argv [i], buf);
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
853 MONO_REQ_GC_NEUTRAL_MODE;
856 g_assert_not_reached ();
861 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
865 case MONO_TYPE_BOOLEAN:
879 case MONO_TYPE_STRING:
880 case MONO_TYPE_OBJECT:
881 case MONO_TYPE_TYPEDBYREF:
882 sigbuffer_add_value (buf, type->type);
885 sigbuffer_add_value (buf, type->type);
886 encode_type (assembly, type->data.type, buf);
888 case MONO_TYPE_SZARRAY:
889 sigbuffer_add_value (buf, type->type);
890 encode_type (assembly, &type->data.klass->byval_arg, buf);
892 case MONO_TYPE_VALUETYPE:
893 case MONO_TYPE_CLASS: {
894 MonoClass *k = mono_class_from_mono_type (type);
896 if (k->generic_container) {
897 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898 encode_generic_class (assembly, gclass, buf);
901 * Make sure we use the correct type.
903 sigbuffer_add_value (buf, k->byval_arg.type);
905 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906 * otherwise two typerefs could point to the same type, leading to
907 * verification errors.
909 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
913 case MONO_TYPE_ARRAY:
914 sigbuffer_add_value (buf, type->type);
915 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916 sigbuffer_add_value (buf, type->data.array->rank);
917 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918 sigbuffer_add_value (buf, 0);
920 case MONO_TYPE_GENERICINST:
921 encode_generic_class (assembly, type->data.generic_class, buf);
925 sigbuffer_add_value (buf, type->type);
926 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
929 g_error ("need to encode type %x", type->type);
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
936 MONO_REQ_GC_UNSAFE_MODE;
938 mono_error_init (error);
941 sigbuffer_add_value (buf, MONO_TYPE_VOID);
945 MonoType *t = mono_reflection_type_get_handle (type, error);
946 return_if_nok (error);
947 encode_type (assembly, t, buf);
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
953 MONO_REQ_GC_UNSAFE_MODE;
957 mono_error_init (error);
960 for (i = 0; i < mono_array_length (modreq); ++i) {
961 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962 return_if_nok (error);
963 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
968 for (i = 0; i < mono_array_length (modopt); ++i) {
969 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970 return_if_nok (error);
971 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
977 #ifndef DISABLE_REFLECTION_EMIT
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
981 MONO_REQ_GC_UNSAFE_MODE;
985 guint32 nparams = sig->param_count;
991 sigbuffer_init (&buf, 32);
993 * FIXME: vararg, explicit_this, differenc call_conv values...
995 idx = sig->call_convention;
997 idx |= 0x20; /* hasthis */
998 if (sig->generic_param_count)
999 idx |= 0x10; /* generic */
1000 sigbuffer_add_byte (&buf, idx);
1001 if (sig->generic_param_count)
1002 sigbuffer_add_value (&buf, sig->generic_param_count);
1003 sigbuffer_add_value (&buf, nparams);
1004 encode_type (assembly, sig->ret, &buf);
1005 for (i = 0; i < nparams; ++i) {
1006 if (i == sig->sentinelpos)
1007 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008 encode_type (assembly, sig->params [i], &buf);
1010 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011 sigbuffer_free (&buf);
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1019 MONO_REQ_GC_UNSAFE_MODE;
1021 mono_error_init (error);
1024 * FIXME: reuse code from method_encode_signature().
1028 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1029 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1033 sigbuffer_init (&buf, 32);
1034 /* LAMESPEC: all the call conv spec is foobared */
1035 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036 if (mb->call_conv & 2)
1037 idx |= 0x5; /* vararg */
1038 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039 idx |= 0x20; /* hasthis */
1041 idx |= 0x10; /* generic */
1042 sigbuffer_add_byte (&buf, idx);
1044 sigbuffer_add_value (&buf, ngparams);
1045 sigbuffer_add_value (&buf, nparams + notypes);
1046 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1049 encode_reflection_type (assembly, mb->rtype, &buf, error);
1052 for (i = 0; i < nparams; ++i) {
1053 MonoArray *modreq = NULL;
1054 MonoArray *modopt = NULL;
1055 MonoReflectionType *pt;
1057 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1064 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065 encode_reflection_type (assembly, pt, &buf, error);
1070 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071 for (i = 0; i < notypes; ++i) {
1072 MonoReflectionType *pt;
1074 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075 encode_reflection_type (assembly, pt, &buf, error);
1080 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1082 sigbuffer_free (&buf);
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1089 MONO_REQ_GC_UNSAFE_MODE;
1091 mono_error_init (error);
1093 MonoDynamicTable *table;
1095 guint32 idx, sig_idx;
1096 guint nl = mono_array_length (ilgen->locals);
1100 sigbuffer_init (&buf, 32);
1101 sigbuffer_add_value (&buf, 0x07);
1102 sigbuffer_add_value (&buf, nl);
1103 for (i = 0; i < nl; ++i) {
1104 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1107 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1109 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110 if (!is_ok (error)) {
1111 sigbuffer_free (&buf);
1115 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116 sigbuffer_free (&buf);
1118 if (assembly->standalonesig_cache == NULL)
1119 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1124 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125 idx = table->next_idx ++;
1127 alloc_table (table, table->rows);
1128 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1130 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1132 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1140 MONO_REQ_GC_UNSAFE_MODE;
1142 guint32 num_clauses = 0;
1145 MonoILExceptionInfo *ex_info;
1146 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148 if (ex_info->handlers)
1149 num_clauses += mono_array_length (ex_info->handlers);
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1161 MONO_REQ_GC_UNSAFE_MODE;
1163 mono_error_init (error);
1165 MonoExceptionClause *clauses;
1166 MonoExceptionClause *clause;
1167 MonoILExceptionInfo *ex_info;
1168 MonoILExceptionBlock *ex_block;
1169 guint32 finally_start;
1170 int i, j, clause_index;;
1172 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1175 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177 finally_start = ex_info->start + ex_info->len;
1178 if (!ex_info->handlers)
1180 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182 clause = &(clauses [clause_index]);
1184 clause->flags = ex_block->type;
1185 clause->try_offset = ex_info->start;
1187 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188 clause->try_len = finally_start - ex_info->start;
1190 clause->try_len = ex_info->len;
1191 clause->handler_offset = ex_block->start;
1192 clause->handler_len = ex_block->len;
1193 if (ex_block->extype) {
1194 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1196 if (!is_ok (error)) {
1197 image_g_free (image, clauses);
1200 clause->data.catch_class = mono_class_from_mono_type (extype);
1202 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203 clause->data.filter_offset = ex_block->filter_offset;
1205 clause->data.filter_offset = 0;
1207 finally_start = ex_block->start + ex_block->len;
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1218 * method_encode_code:
1220 * @assembly the assembly
1221 * @mb the managed MethodBuilder
1222 * @error set on error
1224 * Note that the return value is not sensible if @error is set.
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1229 MONO_REQ_GC_UNSAFE_MODE;
1234 gint32 max_stack, i;
1235 gint32 num_locals = 0;
1236 gint32 num_exception = 0;
1239 char fat_header [12];
1241 guint16 short_value;
1242 guint32 local_sig = 0;
1243 guint32 header_size = 12;
1246 mono_error_init (error);
1248 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1253 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1255 code = mb->ilgen->code;
1256 code_size = mb->ilgen->code_len;
1257 max_stack = mb->ilgen->max_stack;
1258 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259 if (mb->ilgen->ex_handlers)
1260 num_exception = method_count_clauses (mb->ilgen);
1264 char *name = mono_string_to_utf8 (mb->name);
1265 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1272 code_size = mono_array_length (code);
1273 max_stack = 8; /* we probably need to run a verifier on the code... */
1276 stream_data_align (&assembly->code);
1278 /* check for exceptions, maxstack, locals */
1279 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1281 if (code_size < 64 && !(code_size & 1)) {
1282 flags = (code_size << 2) | 0x2;
1283 } else if (code_size < 32 && (code_size & 1)) {
1284 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1288 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289 /* add to the fixup todo list */
1290 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293 return assembly->text_rva + idx;
1297 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298 return_val_if_nok (error, 0);
1301 * FIXME: need to set also the header size in fat_flags.
1302 * (and more sects and init locals flags)
1306 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307 if (mb->init_locals)
1308 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309 fat_header [0] = fat_flags;
1310 fat_header [1] = (header_size / 4 ) << 4;
1311 short_value = GUINT16_TO_LE (max_stack);
1312 memcpy (fat_header + 2, &short_value, 2);
1313 int_value = GUINT32_TO_LE (code_size);
1314 memcpy (fat_header + 4, &int_value, 4);
1315 int_value = GUINT32_TO_LE (local_sig);
1316 memcpy (fat_header + 8, &int_value, 4);
1317 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318 /* add to the fixup todo list */
1319 if (mb->ilgen && mb->ilgen->num_token_fixups)
1320 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1322 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323 if (num_exception) {
1324 unsigned char sheader [4];
1325 MonoILExceptionInfo * ex_info;
1326 MonoILExceptionBlock * ex_block;
1329 stream_data_align (&assembly->code);
1330 /* always use fat format for now */
1331 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332 num_exception *= 6 * sizeof (guint32);
1333 num_exception += 4; /* include the size of the header */
1334 sheader [1] = num_exception & 0xff;
1335 sheader [2] = (num_exception >> 8) & 0xff;
1336 sheader [3] = (num_exception >> 16) & 0xff;
1337 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338 /* fat header, so we are already aligned */
1340 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342 if (ex_info->handlers) {
1343 int finally_start = ex_info->start + ex_info->len;
1344 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1346 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1348 val = GUINT32_TO_LE (ex_block->type);
1349 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1351 val = GUINT32_TO_LE (ex_info->start);
1352 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353 /* need fault, too, probably */
1354 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355 val = GUINT32_TO_LE (finally_start - ex_info->start);
1357 val = GUINT32_TO_LE (ex_info->len);
1358 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359 /* handler offset */
1360 val = GUINT32_TO_LE (ex_block->start);
1361 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1363 val = GUINT32_TO_LE (ex_block->len);
1364 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365 finally_start = ex_block->start + ex_block->len;
1366 if (ex_block->extype) {
1367 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368 return_val_if_nok (error, 0);
1370 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1372 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373 val = ex_block->filter_offset;
1377 val = GUINT32_TO_LE (val);
1378 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1380 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1383 g_error ("No clauses for ex info block %d", i);
1387 return assembly->text_rva + idx;
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1393 MONO_REQ_GC_NEUTRAL_MODE;
1396 MonoDynamicTable *table;
1399 table = &assembly->tables [table_idx];
1401 g_assert (col < table->columns);
1403 values = table->values + table->columns;
1404 for (i = 1; i <= table->rows; ++i) {
1405 if (values [col] == token)
1407 values += table->columns;
1413 * LOCKING: Acquires the loader lock.
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1418 MONO_REQ_GC_NEUTRAL_MODE;
1420 MonoCustomAttrInfo* res;
1422 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1427 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1435 MONO_REQ_GC_UNSAFE_MODE;
1437 /* FIXME: Need to do more checks */
1438 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1441 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1451 MONO_REQ_GC_UNSAFE_MODE;
1453 int i, index, count, not_visible;
1454 MonoCustomAttrInfo *ainfo;
1455 MonoReflectionCustomAttr *cattr;
1459 /* FIXME: check in assembly the Run flag is set */
1461 count = mono_array_length (cattrs);
1463 /* Skip nonpublic attributes since MS.NET seems to do the same */
1464 /* FIXME: This needs to be done more globally */
1466 for (i = 0; i < count; ++i) {
1467 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468 if (!custom_attr_visible (image, cattr))
1471 count -= not_visible;
1473 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1475 ainfo->image = image;
1476 ainfo->num_attrs = count;
1477 ainfo->cached = alloc_img != NULL;
1479 for (i = 0; i < count; ++i) {
1480 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481 if (custom_attr_visible (image, cattr)) {
1482 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484 ainfo->attrs [index].ctor = cattr->ctor->method;
1485 ainfo->attrs [index].data = saved;
1486 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1494 #ifndef DISABLE_REFLECTION_EMIT
1496 * LOCKING: Acquires the loader lock.
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1501 MONO_REQ_GC_UNSAFE_MODE;
1503 MonoCustomAttrInfo *ainfo, *tmp;
1505 if (!cattrs || !mono_array_length (cattrs))
1508 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1510 mono_loader_lock ();
1511 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1513 mono_custom_attrs_free (tmp);
1514 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515 mono_loader_unlock ();
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1523 MONO_REQ_GC_NEUTRAL_MODE;
1525 if (ainfo && !ainfo->cached)
1530 * idx is the table index of the object
1531 * type is one of MONO_CUSTOM_ATTR_*
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1536 MONO_REQ_GC_UNSAFE_MODE;
1538 MonoDynamicTable *table;
1539 MonoReflectionCustomAttr *cattr;
1541 guint32 count, i, token;
1543 char *p = blob_size;
1545 mono_error_init (error);
1547 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1550 count = mono_array_length (cattrs);
1551 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552 table->rows += count;
1553 alloc_table (table, table->rows);
1554 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555 idx <<= MONO_CUSTOM_ATTR_BITS;
1557 for (i = 0; i < count; ++i) {
1558 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561 if (!mono_error_ok (error)) goto fail;
1562 type = mono_metadata_token_index (token);
1563 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564 switch (mono_metadata_token_table (token)) {
1565 case MONO_TABLE_METHOD:
1566 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1568 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569 * method, not the one returned by mono_image_create_token ().
1571 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1573 case MONO_TABLE_MEMBERREF:
1574 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1577 g_warning ("got wrong token in custom attr");
1580 values [MONO_CUSTOM_ATTR_TYPE] = type;
1582 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585 values += MONO_CUSTOM_ATTR_SIZE;
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1598 MONO_REQ_GC_UNSAFE_MODE;
1600 MonoDynamicTable *table;
1602 guint32 count, i, idx;
1603 MonoReflectionPermissionSet *perm;
1608 count = mono_array_length (permissions);
1609 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610 table->rows += count;
1611 alloc_table (table, table->rows);
1613 for (i = 0; i < mono_array_length (permissions); ++i) {
1614 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1616 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1618 idx = mono_metadata_token_index (parent_token);
1619 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620 switch (mono_metadata_token_table (parent_token)) {
1621 case MONO_TABLE_TYPEDEF:
1622 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1624 case MONO_TABLE_METHOD:
1625 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1627 case MONO_TABLE_ASSEMBLY:
1628 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1631 g_assert_not_reached ();
1634 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635 values [MONO_DECL_SECURITY_PARENT] = idx;
1636 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1643 * Fill in the MethodDef and ParamDef tables for a method.
1644 * This is used for both normal methods and constructors.
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1649 MONO_REQ_GC_UNSAFE_MODE;
1651 MonoDynamicTable *table;
1655 mono_error_init (error);
1657 /* room in this table is already allocated */
1658 table = &assembly->tables [MONO_TABLE_METHOD];
1659 *mb->table_idx = table->next_idx ++;
1660 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663 values [MONO_METHOD_FLAGS] = mb->attrs;
1664 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666 return_val_if_nok (error, FALSE);
1667 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668 return_val_if_nok (error, FALSE);
1670 table = &assembly->tables [MONO_TABLE_PARAM];
1671 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1673 mono_image_add_decl_security (assembly,
1674 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1677 MonoDynamicTable *mtable;
1680 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1684 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685 if (mono_array_get (mb->pinfo, gpointer, i))
1688 table->rows += count;
1689 alloc_table (table, table->rows);
1690 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692 MonoReflectionParamBuilder *pb;
1693 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694 values [MONO_PARAM_FLAGS] = pb->attrs;
1695 values [MONO_PARAM_SEQUENCE] = i;
1696 if (pb->name != NULL) {
1697 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1699 values [MONO_PARAM_NAME] = 0;
1701 values += MONO_PARAM_SIZE;
1702 if (pb->marshal_info) {
1704 alloc_table (mtable, mtable->rows);
1705 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708 return_val_if_nok (error, FALSE);
1710 pb->table_idx = table->next_idx++;
1711 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712 guint32 field_type = 0;
1713 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1715 alloc_table (mtable, mtable->rows);
1716 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719 mvalues [MONO_CONSTANT_TYPE] = field_type;
1720 mvalues [MONO_CONSTANT_PADDING] = 0;
1729 #ifndef DISABLE_REFLECTION_EMIT
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1733 MONO_REQ_GC_UNSAFE_MODE;
1735 mono_error_init (error);
1736 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1738 rmb->ilgen = mb->ilgen;
1739 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740 return_val_if_nok (error, FALSE);
1741 rmb->parameters = mb->parameters;
1742 rmb->generic_params = mb->generic_params;
1743 rmb->generic_container = mb->generic_container;
1744 rmb->opt_types = NULL;
1745 rmb->pinfo = mb->pinfo;
1746 rmb->attrs = mb->attrs;
1747 rmb->iattrs = mb->iattrs;
1748 rmb->call_conv = mb->call_conv;
1749 rmb->code = mb->code;
1750 rmb->type = mb->type;
1751 rmb->name = mb->name;
1752 rmb->table_idx = &mb->table_idx;
1753 rmb->init_locals = mb->init_locals;
1754 rmb->skip_visibility = FALSE;
1755 rmb->return_modreq = mb->return_modreq;
1756 rmb->return_modopt = mb->return_modopt;
1757 rmb->param_modreq = mb->param_modreq;
1758 rmb->param_modopt = mb->param_modopt;
1759 rmb->permissions = mb->permissions;
1760 rmb->mhandle = mb->mhandle;
1765 rmb->charset = mb->charset;
1766 rmb->extra_flags = mb->extra_flags;
1767 rmb->native_cc = mb->native_cc;
1768 rmb->dllentry = mb->dllentry;
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1778 MONO_REQ_GC_UNSAFE_MODE;
1780 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1782 mono_error_init (error);
1784 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1786 rmb->ilgen = mb->ilgen;
1787 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788 return_val_if_nok (error, FALSE);
1789 rmb->parameters = mb->parameters;
1790 rmb->generic_params = NULL;
1791 rmb->generic_container = NULL;
1792 rmb->opt_types = NULL;
1793 rmb->pinfo = mb->pinfo;
1794 rmb->attrs = mb->attrs;
1795 rmb->iattrs = mb->iattrs;
1796 rmb->call_conv = mb->call_conv;
1798 rmb->type = mb->type;
1799 rmb->name = mono_string_new (mono_domain_get (), name);
1800 rmb->table_idx = &mb->table_idx;
1801 rmb->init_locals = mb->init_locals;
1802 rmb->skip_visibility = FALSE;
1803 rmb->return_modreq = NULL;
1804 rmb->return_modopt = NULL;
1805 rmb->param_modreq = mb->param_modreq;
1806 rmb->param_modopt = mb->param_modopt;
1807 rmb->permissions = mb->permissions;
1808 rmb->mhandle = mb->mhandle;
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1818 MONO_REQ_GC_UNSAFE_MODE;
1820 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1822 rmb->ilgen = mb->ilgen;
1823 rmb->rtype = mb->rtype;
1824 rmb->parameters = mb->parameters;
1825 rmb->generic_params = NULL;
1826 rmb->generic_container = NULL;
1827 rmb->opt_types = NULL;
1829 rmb->attrs = mb->attrs;
1831 rmb->call_conv = mb->call_conv;
1833 rmb->type = (MonoObject *) mb->owner;
1834 rmb->name = mb->name;
1835 rmb->table_idx = NULL;
1836 rmb->init_locals = mb->init_locals;
1837 rmb->skip_visibility = mb->skip_visibility;
1838 rmb->return_modreq = NULL;
1839 rmb->return_modopt = NULL;
1840 rmb->param_modreq = NULL;
1841 rmb->param_modopt = NULL;
1842 rmb->permissions = NULL;
1843 rmb->mhandle = mb->mhandle;
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1852 MONO_REQ_GC_UNSAFE_MODE;
1854 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855 MonoDynamicTable *table;
1858 MonoReflectionMethod *m;
1861 mono_error_init (error);
1863 if (!mb->override_methods)
1866 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1869 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1871 alloc_table (table, table->rows);
1872 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1876 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877 return_val_if_nok (error, FALSE);
1879 switch (mono_metadata_token_table (tok)) {
1880 case MONO_TABLE_MEMBERREF:
1881 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1883 case MONO_TABLE_METHOD:
1884 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1887 g_assert_not_reached ();
1889 values [MONO_METHODIMPL_DECLARATION] = tok;
1895 #ifndef DISABLE_REFLECTION_EMIT
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1899 MONO_REQ_GC_UNSAFE_MODE;
1901 MonoDynamicTable *table;
1903 ReflectionMethodBuilder rmb;
1906 mono_error_init (error);
1908 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909 !mono_image_basic_method (&rmb, assembly, error))
1912 mb->table_idx = *rmb.table_idx;
1914 if (mb->dll) { /* It's a P/Invoke method */
1916 /* map CharSet values to on-disk values */
1917 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918 int extra_flags = mb->extra_flags;
1919 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1921 alloc_table (table, table->rows);
1922 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1924 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1927 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1929 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932 table = &assembly->tables [MONO_TABLE_MODULEREF];
1934 alloc_table (table, table->rows);
1935 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936 values [MONO_IMPLMAP_SCOPE] = table->rows;
1940 if (mb->generic_params) {
1941 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942 table->rows += mono_array_length (mb->generic_params);
1943 alloc_table (table, table->rows);
1944 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1947 mono_image_get_generic_param_info (
1948 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1958 MONO_REQ_GC_UNSAFE_MODE;
1960 ReflectionMethodBuilder rmb;
1962 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1965 if (!mono_image_basic_method (&rmb, assembly, error))
1968 mb->table_idx = *rmb.table_idx;
1975 type_get_fully_qualified_name (MonoType *type)
1977 MONO_REQ_GC_NEUTRAL_MODE;
1979 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1985 MONO_REQ_GC_UNSAFE_MODE;
1990 klass = mono_class_from_mono_type (type);
1992 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993 ta = klass->image->assembly;
1994 if (assembly_is_dynamic (ta) || (ta == ass)) {
1995 if (klass->generic_class || klass->generic_container)
1996 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1999 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2010 MONO_REQ_GC_NEUTRAL_MODE;
2013 guint32 idx, i, token;
2015 if (!assembly->save)
2018 sigbuffer_init (&buf, 32);
2020 sigbuffer_add_value (&buf, 0x06);
2021 /* encode custom attributes before the type */
2022 if (type->num_mods) {
2023 for (i = 0; i < type->num_mods; ++i) {
2026 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2029 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2031 token = type->modifiers [i].token;
2034 if (type->modifiers [i].required)
2035 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2037 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2039 sigbuffer_add_value (&buf, token);
2042 encode_type (assembly, type, &buf);
2043 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044 sigbuffer_free (&buf);
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2052 MONO_REQ_GC_UNSAFE_MODE;
2054 mono_error_init (error);
2058 guint32 typespec = 0;
2062 init_type_builder_generics (fb->type);
2064 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065 return_val_if_nok (error, 0);
2066 klass = mono_class_from_mono_type (type);
2068 sigbuffer_init (&buf, 32);
2070 sigbuffer_add_value (&buf, 0x06);
2071 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2074 /* encode custom attributes before the type */
2076 if (klass->generic_container)
2077 typespec = create_typespec (assembly, type);
2080 MonoGenericClass *gclass;
2081 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082 encode_generic_class (assembly, gclass, &buf);
2084 encode_type (assembly, type, &buf);
2086 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087 sigbuffer_free (&buf);
2090 sigbuffer_free (&buf);
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2097 MONO_REQ_GC_UNSAFE_MODE;
2099 char blob_size [64];
2100 char *b = blob_size;
2103 guint32 idx = 0, len = 0, dummy = 0;
2105 buf = (char *)g_malloc (64);
2107 *ret_type = MONO_TYPE_CLASS;
2109 box_val = (char*)&dummy;
2111 box_val = ((char*)val) + sizeof (MonoObject);
2112 *ret_type = val->vtable->klass->byval_arg.type;
2115 switch (*ret_type) {
2116 case MONO_TYPE_BOOLEAN:
2121 case MONO_TYPE_CHAR:
2138 case MONO_TYPE_VALUETYPE: {
2139 MonoClass *klass = val->vtable->klass;
2141 if (klass->enumtype) {
2142 *ret_type = mono_class_enum_basetype (klass)->type;
2144 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2147 g_error ("we can't encode valuetypes, we should have never reached this line");
2150 case MONO_TYPE_CLASS:
2152 case MONO_TYPE_STRING: {
2153 MonoString *str = (MonoString*)val;
2154 /* there is no signature */
2155 len = str->length * 2;
2156 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2159 char *swapped = g_malloc (2 * mono_string_length (str));
2160 const char *p = (const char*)mono_string_chars (str);
2162 swap_with_size (swapped, p, 2, mono_string_length (str));
2163 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2173 case MONO_TYPE_GENERICINST:
2174 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2177 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2180 /* there is no signature */
2181 mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184 swap_with_size (blob_size, box_val, len, 1);
2185 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2187 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2197 MONO_REQ_GC_UNSAFE_MODE;
2199 mono_error_init (error);
2205 sigbuffer_init (&buf, 32);
2207 sigbuffer_add_value (&buf, minfo->type);
2209 switch (minfo->type) {
2210 case MONO_NATIVE_BYVALTSTR:
2211 case MONO_NATIVE_BYVALARRAY:
2212 sigbuffer_add_value (&buf, minfo->count);
2214 case MONO_NATIVE_LPARRAY:
2215 if (minfo->eltype || minfo->has_size) {
2216 sigbuffer_add_value (&buf, minfo->eltype);
2217 if (minfo->has_size) {
2218 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2221 /* LAMESPEC: ElemMult is undocumented */
2222 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2226 case MONO_NATIVE_SAFEARRAY:
2228 sigbuffer_add_value (&buf, minfo->eltype);
2230 case MONO_NATIVE_CUSTOM:
2232 str = mono_string_to_utf8 (minfo->guid);
2234 sigbuffer_add_value (&buf, len);
2235 sigbuffer_add_mem (&buf, str, len);
2238 sigbuffer_add_value (&buf, 0);
2240 /* native type name */
2241 sigbuffer_add_value (&buf, 0);
2242 /* custom marshaler type name */
2243 if (minfo->marshaltype || minfo->marshaltyperef) {
2244 if (minfo->marshaltyperef) {
2245 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246 if (!is_ok (error)) {
2247 sigbuffer_free (&buf);
2250 str = type_get_fully_qualified_name (marshaltype);
2252 str = mono_string_to_utf8 (minfo->marshaltype);
2254 sigbuffer_add_value (&buf, len);
2255 sigbuffer_add_mem (&buf, str, len);
2258 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2259 sigbuffer_add_value (&buf, 0);
2261 if (minfo->mcookie) {
2262 str = mono_string_to_utf8 (minfo->mcookie);
2264 sigbuffer_add_value (&buf, len);
2265 sigbuffer_add_mem (&buf, str, len);
2268 sigbuffer_add_value (&buf, 0);
2274 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275 sigbuffer_free (&buf);
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2282 MONO_REQ_GC_UNSAFE_MODE;
2284 mono_error_init (error);
2286 MonoDynamicTable *table;
2289 /* maybe this fixup should be done in the C# code */
2290 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292 table = &assembly->tables [MONO_TABLE_FIELD];
2293 fb->table_idx = table->next_idx ++;
2294 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297 values [MONO_FIELD_FLAGS] = fb->attrs;
2298 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299 return_if_nok (error);
2302 if (fb->offset != -1) {
2303 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2305 alloc_table (table, table->rows);
2306 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2310 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312 table = &assembly->tables [MONO_TABLE_CONSTANT];
2314 alloc_table (table, table->rows);
2315 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318 values [MONO_CONSTANT_TYPE] = field_type;
2319 values [MONO_CONSTANT_PADDING] = 0;
2321 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2323 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2325 alloc_table (table, table->rows);
2326 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2329 * We store it in the code section because it's simpler for now.
2332 if (mono_array_length (fb->rva_data) >= 10)
2333 stream_data_align (&assembly->code);
2334 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2336 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2339 if (fb->marshal_info) {
2340 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2342 alloc_table (table, table->rows);
2343 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346 return_if_nok (error);
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2353 MONO_REQ_GC_UNSAFE_MODE;
2355 mono_error_init (error);
2358 guint32 nparams = 0;
2359 MonoReflectionMethodBuilder *mb = fb->get_method;
2360 MonoReflectionMethodBuilder *smb = fb->set_method;
2363 if (mb && mb->parameters)
2364 nparams = mono_array_length (mb->parameters);
2365 if (!mb && smb && smb->parameters)
2366 nparams = mono_array_length (smb->parameters) - 1;
2367 sigbuffer_init (&buf, 32);
2368 if (fb->call_conv & 0x20)
2369 sigbuffer_add_byte (&buf, 0x28);
2371 sigbuffer_add_byte (&buf, 0x08);
2372 sigbuffer_add_value (&buf, nparams);
2374 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2377 for (i = 0; i < nparams; ++i) {
2378 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379 encode_reflection_type (assembly, pt, &buf, error);
2383 } else if (smb && smb->parameters) {
2384 /* the property type is the last param */
2385 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2389 for (i = 0; i < nparams; ++i) {
2390 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391 encode_reflection_type (assembly, pt, &buf, error);
2396 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2401 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402 sigbuffer_free (&buf);
2405 sigbuffer_free (&buf);
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2412 MONO_REQ_GC_UNSAFE_MODE;
2414 mono_error_init (error);
2416 MonoDynamicTable *table;
2418 guint num_methods = 0;
2422 * we need to set things in the following tables:
2423 * PROPERTYMAP (info already filled in _get_type_info ())
2424 * PROPERTY (rows already preallocated in _get_type_info ())
2425 * METHOD (method info already done with the generic method code)
2429 table = &assembly->tables [MONO_TABLE_PROPERTY];
2430 pb->table_idx = table->next_idx ++;
2431 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435 return_if_nok (error);
2438 /* FIXME: we still don't handle 'other' methods */
2439 if (pb->get_method) num_methods ++;
2440 if (pb->set_method) num_methods ++;
2442 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443 table->rows += num_methods;
2444 alloc_table (table, table->rows);
2446 if (pb->get_method) {
2447 semaidx = table->next_idx ++;
2448 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2453 if (pb->set_method) {
2454 semaidx = table->next_idx ++;
2455 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2460 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462 table = &assembly->tables [MONO_TABLE_CONSTANT];
2464 alloc_table (table, table->rows);
2465 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468 values [MONO_CONSTANT_TYPE] = field_type;
2469 values [MONO_CONSTANT_PADDING] = 0;
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, 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);
2969 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2970 return_val_if_nok (error, 0);
2972 parent = mono_image_typedef_or_ref (assembly, t);
2975 char *name = mono_string_to_utf8 (method->name);
2977 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2980 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2986 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2987 const gchar *name, guint32 sig)
2989 MonoDynamicTable *table;
2993 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2995 if (assembly->save) {
2996 alloc_table (table, table->rows + 1);
2997 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2998 values [MONO_MEMBERREF_CLASS] = original;
2999 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3000 values [MONO_MEMBERREF_SIGNATURE] = sig;
3003 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3010 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3014 guint32 nparams = mono_array_length (mb->generic_params);
3017 if (!assembly->save)
3020 sigbuffer_init (&buf, 32);
3022 sigbuffer_add_value (&buf, 0xa);
3023 sigbuffer_add_value (&buf, nparams);
3025 for (i = 0; i < nparams; i++) {
3026 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3027 sigbuffer_add_value (&buf, i);
3030 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3031 sigbuffer_free (&buf);
3036 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3038 MonoDynamicTable *table;
3040 guint32 token, mtoken = 0;
3042 mono_error_init (error);
3043 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3047 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3049 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3050 if (!mono_error_ok (error))
3053 switch (mono_metadata_token_table (mtoken)) {
3054 case MONO_TABLE_MEMBERREF:
3055 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3057 case MONO_TABLE_METHOD:
3058 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3061 g_assert_not_reached ();
3064 if (assembly->save) {
3065 alloc_table (table, table->rows + 1);
3066 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3067 values [MONO_METHODSPEC_METHOD] = mtoken;
3068 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3071 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3074 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3079 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3083 mono_error_init (error);
3085 if (mb->generic_params && create_methodspec)
3086 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3088 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3092 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3093 if (!mono_error_ok (error))
3095 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3100 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3102 guint32 token, parent, sig;
3103 ReflectionMethodBuilder rmb;
3105 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3107 mono_error_init (error);
3109 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3113 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3116 if (tb->generic_params)
3117 parent = create_generic_typespec (assembly, tb);
3119 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3120 return_val_if_nok (error, 0);
3121 parent = mono_image_typedef_or_ref (assembly, type);
3124 name = mono_string_to_utf8 (rmb.name);
3125 sig = method_builder_encode_signature (assembly, &rmb, error);
3126 return_val_if_nok (error, 0);
3128 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3131 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3137 is_field_on_inst (MonoClassField *field)
3139 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3143 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3146 get_field_on_inst_generic_type (MonoClassField *field)
3148 MonoClass *klass, *gtd;
3149 MonoDynamicGenericClass *dgclass;
3152 g_assert (is_field_on_inst (field));
3154 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3156 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3157 field_index = field - dgclass->fields;
3158 return dgclass->field_generic_types [field_index];
3161 klass = field->parent;
3162 gtd = klass->generic_class->container_class;
3164 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3165 field_index = field - klass->fields;
3166 return gtd->fields [field_index].type;
3169 g_assert_not_reached ();
3173 #ifndef DISABLE_REFLECTION_EMIT
3175 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3181 g_assert (field->parent);
3183 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3187 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3188 int index = field - field->parent->fields;
3189 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3191 if (is_field_on_inst (field))
3192 type = get_field_on_inst_generic_type (field);
3194 type = mono_field_get_type (field);
3196 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3197 mono_field_get_name (field),
3198 fieldref_encode_signature (assembly, field->parent->image, type));
3199 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3204 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3208 MonoGenericClass *gclass;
3212 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215 if (is_sre_field_builder (mono_object_class (f->fb))) {
3216 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3217 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3218 return_val_if_nok (error, 0);
3219 klass = mono_class_from_mono_type (type);
3220 gclass = type->data.generic_class;
3221 g_assert (gclass->is_dynamic);
3223 guint32 sig_token = field_encode_signature (assembly, fb, error);
3224 return_val_if_nok (error, 0);
3225 name = mono_string_to_utf8 (fb->name);
3226 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3228 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3230 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3232 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3233 return_val_if_nok (error, 0);
3234 klass = mono_class_from_mono_type (type);
3236 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3237 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3239 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3240 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3243 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3248 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3252 MonoGenericClass *gclass;
3255 mono_error_init (error);
3257 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3259 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3263 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3264 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3265 ReflectionMethodBuilder rmb;
3268 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3269 return_val_if_nok (error, 0);
3270 klass = mono_class_from_mono_type (type);
3272 gclass = type->data.generic_class;
3273 g_assert (gclass->is_dynamic);
3275 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278 sig = method_builder_encode_signature (assembly, &rmb, error);
3279 return_val_if_nok (error, 0);
3281 name = mono_string_to_utf8 (rmb.name);
3283 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3285 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3286 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3288 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3289 return_val_if_nok (error, 0);
3290 klass = mono_class_from_mono_type (type);
3292 sig = method_encode_signature (assembly, mono_method_signature (mm));
3293 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3295 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3296 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3300 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3305 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3308 MonoGenericContext tmp_context;
3309 MonoType **type_argv;
3310 MonoGenericInst *ginst;
3311 MonoMethod *method, *inflated;
3314 mono_error_init (error);
3316 init_type_builder_generics ((MonoObject*)m->inst);
3318 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3319 return_val_if_nok (error, NULL);
3321 klass = method->klass;
3323 if (m->method_args == NULL)
3326 if (method->is_inflated)
3327 method = ((MonoMethodInflated *) method)->declaring;
3329 count = mono_array_length (m->method_args);
3331 type_argv = g_new0 (MonoType *, count);
3332 for (i = 0; i < count; i++) {
3333 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3334 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3335 return_val_if_nok (error, NULL);
3337 ginst = mono_metadata_get_generic_inst (count, type_argv);
3340 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3341 tmp_context.method_inst = ginst;
3343 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3344 mono_error_assert_ok (error);
3349 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3351 guint32 sig, token = 0;
3355 mono_error_init (error);
3357 if (m->method_args) {
3358 MonoMethod *inflated;
3360 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3361 return_val_if_nok (error, 0);
3363 if (create_methodspec)
3364 token = mono_image_get_methodspec_token (assembly, inflated);
3366 token = mono_image_get_inflated_method_token (assembly, inflated);
3370 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3374 if (is_sre_method_builder (mono_object_class (m->mb))) {
3375 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3376 MonoGenericClass *gclass;
3377 ReflectionMethodBuilder rmb;
3380 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3381 return_val_if_nok (error, 0);
3382 klass = mono_class_from_mono_type (type);
3383 gclass = type->data.generic_class;
3384 g_assert (gclass->is_dynamic);
3386 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389 sig = method_builder_encode_signature (assembly, &rmb, error);
3390 return_val_if_nok (error, 0);
3392 name = mono_string_to_utf8 (rmb.name);
3394 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3396 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3397 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3399 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3400 return_val_if_nok (error, 0);
3401 klass = mono_class_from_mono_type (type);
3403 sig = method_encode_signature (assembly, mono_method_signature (mm));
3404 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3406 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3407 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3410 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3419 guint32 nparams = context->method_inst->type_argc;
3422 if (!assembly->save)
3425 sigbuffer_init (&buf, 32);
3427 * FIXME: vararg, explicit_this, differenc call_conv values...
3429 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3430 sigbuffer_add_value (&buf, nparams);
3432 for (i = 0; i < nparams; i++)
3433 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3435 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3436 sigbuffer_free (&buf);
3441 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3443 MonoDynamicTable *table;
3445 guint32 token, mtoken = 0, sig;
3446 MonoMethodInflated *imethod;
3447 MonoMethod *declaring;
3449 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3451 g_assert (method->is_inflated);
3452 imethod = (MonoMethodInflated *) method;
3453 declaring = imethod->declaring;
3455 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3456 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3458 if (!mono_method_signature (declaring)->generic_param_count)
3461 switch (mono_metadata_token_table (mtoken)) {
3462 case MONO_TABLE_MEMBERREF:
3463 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3465 case MONO_TABLE_METHOD:
3466 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469 g_assert_not_reached ();
3472 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3474 if (assembly->save) {
3475 alloc_table (table, table->rows + 1);
3476 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3477 values [MONO_METHODSPEC_METHOD] = mtoken;
3478 values [MONO_METHODSPEC_SIGNATURE] = sig;
3481 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3488 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3490 MonoMethodInflated *imethod;
3493 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3497 g_assert (method->is_inflated);
3498 imethod = (MonoMethodInflated *) method;
3500 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3501 token = method_encode_methodspec (assembly, method);
3503 guint32 sig = method_encode_signature (
3504 assembly, mono_method_signature (imethod->declaring));
3505 token = mono_image_get_memberref_token (
3506 assembly, &method->klass->byval_arg, method->name, sig);
3509 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3514 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3516 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3520 token = mono_image_get_memberref_token (
3521 assembly, &m->klass->byval_arg, m->name, sig);
3527 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3530 MonoDynamicTable *table;
3539 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3540 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3541 * Because of this, we must not insert it into the `typeref' hash table.
3543 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3544 mono_error_raise_exception (&error); /* FIXME don't raise here */
3545 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3549 sigbuffer_init (&buf, 32);
3551 g_assert (tb->generic_params);
3552 klass = mono_class_from_mono_type (type);
3554 if (tb->generic_container)
3555 mono_reflection_create_generic_class (tb);
3557 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3558 g_assert (klass->generic_container);
3559 sigbuffer_add_value (&buf, klass->byval_arg.type);
3560 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3562 count = mono_array_length (tb->generic_params);
3563 sigbuffer_add_value (&buf, count);
3564 for (i = 0; i < count; i++) {
3565 MonoReflectionGenericParam *gparam;
3567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3568 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3569 mono_error_raise_exception (&error); /* FIXME don't raise here */
3571 encode_type (assembly, gparam_type, &buf);
3574 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3576 if (assembly->save) {
3577 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3578 alloc_table (table, table->rows + 1);
3579 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3580 values [MONO_TYPESPEC_SIGNATURE] = token;
3582 sigbuffer_free (&buf);
3584 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3585 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3591 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3594 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3597 int i, count, len, pos;
3602 count += mono_array_length (modreq);
3604 count += mono_array_length (modopt);
3607 return mono_metadata_type_dup (NULL, type);
3609 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3610 t = (MonoType *)g_malloc (len);
3611 memcpy (t, type, MONO_SIZEOF_TYPE);
3613 t->num_mods = count;
3616 for (i = 0; i < mono_array_length (modreq); ++i) {
3617 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3618 mono_error_raise_exception (&error); /* FIXME don't raise here */
3619 t->modifiers [pos].required = 1;
3620 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3625 for (i = 0; i < mono_array_length (modopt); ++i) {
3626 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3627 mono_error_raise_exception (&error); /* FIXME don't raise here */
3628 t->modifiers [pos].required = 0;
3629 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3638 init_type_builder_generics (MonoObject *type)
3640 MonoReflectionTypeBuilder *tb;
3642 if (!is_sre_type_builder(mono_object_class (type)))
3644 tb = (MonoReflectionTypeBuilder *)type;
3646 if (tb && tb->generic_container)
3647 mono_reflection_create_generic_class (tb);
3651 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3654 MonoDynamicTable *table;
3655 MonoType *custom = NULL, *type;
3657 guint32 token, pclass, parent, sig;
3660 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3664 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3665 mono_error_raise_exception (&error); /* FIXME don't raise here */
3666 /* FIXME: is this call necessary? */
3667 mono_class_from_mono_type (typeb);
3668 name = mono_string_to_utf8 (fb->name);
3670 /*FIXME this is one more layer of ugliness due how types are created.*/
3671 init_type_builder_generics (fb->type);
3673 /* fb->type does not include the custom modifiers */
3674 /* FIXME: We should do this in one place when a fieldbuilder is created */
3675 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3676 mono_error_raise_exception (&error); /* FIXME don't raise here */
3678 if (fb->modreq || fb->modopt)
3679 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3681 sig = fieldref_encode_signature (assembly, NULL, type);
3684 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3685 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3687 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3688 parent >>= MONO_TYPEDEFORREF_BITS;
3690 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3692 if (assembly->save) {
3693 alloc_table (table, table->rows + 1);
3694 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3695 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3696 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3697 values [MONO_MEMBERREF_SIGNATURE] = sig;
3700 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3702 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3708 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3715 if (!assembly->save)
3718 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3719 g_assert (helper->type == 2);
3721 if (helper->arguments)
3722 nargs = mono_array_length (helper->arguments);
3726 sigbuffer_init (&buf, 32);
3728 /* Encode calling convention */
3729 /* Change Any to Standard */
3730 if ((helper->call_conv & 0x03) == 0x03)
3731 helper->call_conv = 0x01;
3732 /* explicit_this implies has_this */
3733 if (helper->call_conv & 0x40)
3734 helper->call_conv &= 0x20;
3736 if (helper->call_conv == 0) { /* Unmanaged */
3737 idx = helper->unmanaged_call_conv - 1;
3740 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3741 if (helper->call_conv & 0x02) /* varargs */
3745 sigbuffer_add_byte (&buf, idx);
3746 sigbuffer_add_value (&buf, nargs);
3747 encode_reflection_type (assembly, helper->return_type, &buf, &error);
3748 if (!is_ok (&error))
3750 for (i = 0; i < nargs; ++i) {
3751 MonoArray *modreqs = NULL;
3752 MonoArray *modopts = NULL;
3753 MonoReflectionType *pt;
3755 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3756 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3757 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3758 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3760 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3761 if (!is_ok (&error))
3763 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3764 encode_reflection_type (assembly, pt, &buf, &error);
3765 if (!is_ok (&error))
3768 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3769 sigbuffer_free (&buf);
3773 sigbuffer_free (&buf);
3774 mono_error_raise_exception (&error); /* FIXME don't raise here */
3775 g_assert_not_reached ();
3779 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3782 MonoDynamicTable *table;
3785 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3786 idx = table->next_idx ++;
3788 alloc_table (table, table->rows);
3789 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3791 values [MONO_STAND_ALONE_SIGNATURE] =
3792 mono_reflection_encode_sighelper (assembly, helper);
3798 reflection_cc_to_file (int call_conv) {
3799 switch (call_conv & 0x3) {
3801 case 1: return MONO_CALL_DEFAULT;
3802 case 2: return MONO_CALL_VARARG;
3804 g_assert_not_reached ();
3808 #endif /* !DISABLE_REFLECTION_EMIT */
3812 MonoMethodSignature *sig;
3817 #ifndef DISABLE_REFLECTION_EMIT
3819 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3825 MonoMethodSignature *sig;
3829 name = mono_string_to_utf8 (m->name);
3830 nparams = mono_array_length (m->parameters);
3831 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3833 sig->sentinelpos = -1;
3834 sig->call_convention = reflection_cc_to_file (m->call_conv);
3835 sig->param_count = nparams;
3837 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3838 mono_error_raise_exception (&error); /* FIXME don't raise here */
3840 sig->ret = &mono_defaults.void_class->byval_arg;
3842 mtype = mono_reflection_type_get_handle (m->parent, &error);
3843 mono_error_raise_exception (&error); /* FIXME don't raise here */
3845 for (i = 0; i < nparams; ++i) {
3846 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3847 mono_error_raise_exception (&error); /* FIXME don't raise here */
3850 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3851 am = (ArrayMethod *)tmp->data;
3852 if (strcmp (name, am->name) == 0 &&
3853 mono_metadata_type_equal (am->parent, mtype) &&
3854 mono_metadata_signature_equal (am->sig, sig)) {
3857 m->table_idx = am->token & 0xffffff;
3861 am = g_new0 (ArrayMethod, 1);
3865 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3866 method_encode_signature (assembly, sig));
3867 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3868 m->table_idx = am->token & 0xffffff;
3873 * Insert into the metadata tables all the info about the TypeBuilder tb.
3874 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3877 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3879 MonoDynamicTable *table;
3881 int i, is_object = 0, is_system = 0;
3884 mono_error_init (error);
3886 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3887 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3888 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3889 n = mono_string_to_utf8 (tb->name);
3890 if (strcmp (n, "Object") == 0)
3892 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3894 n = mono_string_to_utf8 (tb->nspace);
3895 if (strcmp (n, "System") == 0)
3897 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3899 if (tb->parent && !(is_system && is_object) &&
3900 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3901 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3902 return_val_if_nok (error, FALSE);
3903 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3905 values [MONO_TYPEDEF_EXTENDS] = 0;
3907 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3908 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3911 * if we have explicitlayout or sequentiallayouts, output data in the
3912 * ClassLayout table.
3914 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3915 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3916 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3918 alloc_table (table, table->rows);
3919 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3920 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3921 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3922 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3925 /* handle interfaces */
3926 if (tb->interfaces) {
3927 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3929 table->rows += mono_array_length (tb->interfaces);
3930 alloc_table (table, table->rows);
3931 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3932 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3933 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3934 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3935 return_val_if_nok (error, FALSE);
3936 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3937 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3938 values += MONO_INTERFACEIMPL_SIZE;
3944 table = &assembly->tables [MONO_TABLE_FIELD];
3945 table->rows += tb->num_fields;
3946 alloc_table (table, table->rows);
3947 for (i = 0; i < tb->num_fields; ++i) {
3948 mono_image_get_field_info (
3949 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3950 return_val_if_nok (error, FALSE);
3954 /* handle constructors */
3956 table = &assembly->tables [MONO_TABLE_METHOD];
3957 table->rows += mono_array_length (tb->ctors);
3958 alloc_table (table, table->rows);
3959 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3960 if (!mono_image_get_ctor_info (domain,
3961 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3967 /* handle methods */
3969 table = &assembly->tables [MONO_TABLE_METHOD];
3970 table->rows += tb->num_methods;
3971 alloc_table (table, table->rows);
3972 for (i = 0; i < tb->num_methods; ++i) {
3973 if (!mono_image_get_method_info (
3974 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3979 /* Do the same with properties etc.. */
3980 if (tb->events && mono_array_length (tb->events)) {
3981 table = &assembly->tables [MONO_TABLE_EVENT];
3982 table->rows += mono_array_length (tb->events);
3983 alloc_table (table, table->rows);
3984 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3986 alloc_table (table, table->rows);
3987 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3988 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3989 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3990 for (i = 0; i < mono_array_length (tb->events); ++i) {
3991 mono_image_get_event_info (
3992 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
3993 return_val_if_nok (error, FALSE);
3996 if (tb->properties && mono_array_length (tb->properties)) {
3997 table = &assembly->tables [MONO_TABLE_PROPERTY];
3998 table->rows += mono_array_length (tb->properties);
3999 alloc_table (table, table->rows);
4000 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4002 alloc_table (table, table->rows);
4003 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4004 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4005 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4006 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4007 mono_image_get_property_info (
4008 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4009 return_val_if_nok (error, FALSE);
4013 /* handle generic parameters */
4014 if (tb->generic_params) {
4015 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4016 table->rows += mono_array_length (tb->generic_params);
4017 alloc_table (table, table->rows);
4018 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4019 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4021 mono_image_get_generic_param_info (
4022 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4026 mono_image_add_decl_security (assembly,
4027 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4030 MonoDynamicTable *ntable;
4032 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4033 ntable->rows += mono_array_length (tb->subtypes);
4034 alloc_table (ntable, ntable->rows);
4035 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4037 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4038 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4040 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4041 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4042 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4043 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4044 mono_string_to_utf8 (tb->name), tb->table_idx,
4045 ntable->next_idx, ntable->rows);*/
4046 values += MONO_NESTED_CLASS_SIZE;
4056 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4060 mono_ptr_array_append (*types, type);
4062 if (!type->subtypes)
4065 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4066 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4067 collect_types (types, subtype);
4072 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4074 if ((*type1)->table_idx < (*type2)->table_idx)
4077 if ((*type1)->table_idx > (*type2)->table_idx)
4084 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4087 mono_error_init (error);
4090 for (i = 0; i < mono_array_length (pinfo); ++i) {
4091 MonoReflectionParamBuilder *pb;
4092 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4095 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4103 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4106 mono_error_init (error);
4108 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4111 for (i = 0; i < tb->num_fields; ++i) {
4112 MonoReflectionFieldBuilder* fb;
4113 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4114 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4119 for (i = 0; i < mono_array_length (tb->events); ++i) {
4120 MonoReflectionEventBuilder* eb;
4121 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4122 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4126 if (tb->properties) {
4127 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4128 MonoReflectionPropertyBuilder* pb;
4129 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4130 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4135 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4136 MonoReflectionCtorBuilder* cb;
4137 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4138 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4139 !params_add_cattrs (assembly, cb->pinfo, error))
4145 for (i = 0; i < tb->num_methods; ++i) {
4146 MonoReflectionMethodBuilder* mb;
4147 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4148 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4149 !params_add_cattrs (assembly, mb->pinfo, error))
4155 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4156 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4165 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4169 mono_error_init (error);
4171 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4174 if (moduleb->global_methods) {
4175 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4176 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4177 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4178 !params_add_cattrs (assembly, mb->pinfo, error))
4183 if (moduleb->global_fields) {
4184 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4185 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4186 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4191 if (moduleb->types) {
4192 for (i = 0; i < moduleb->num_types; ++i) {
4193 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4202 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4204 MonoDynamicTable *table;
4208 char *b = blob_size;
4211 table = &assembly->tables [MONO_TABLE_FILE];
4213 alloc_table (table, table->rows);
4214 values = table->values + table->next_idx * MONO_FILE_SIZE;
4215 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4216 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4217 if (image_is_dynamic (module->image)) {
4218 /* This depends on the fact that the main module is emitted last */
4219 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4220 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4223 path = g_strdup (module->image->name);
4225 mono_sha1_get_digest_from_file (path, hash);
4228 mono_metadata_encode_value (20, b, &b);
4229 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4230 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4235 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4237 MonoDynamicTable *table;
4240 table = &assembly->tables [MONO_TABLE_MODULE];
4241 mb->table_idx = table->next_idx ++;
4242 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4243 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4246 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4247 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4248 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4249 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4253 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4254 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4256 MonoDynamicTable *table;
4260 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4261 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4264 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4266 alloc_table (table, table->rows);
4267 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4269 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4270 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4271 if (klass->nested_in)
4272 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4274 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4275 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4276 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4278 res = table->next_idx;
4282 /* Emit nested types */
4283 if (klass->ext && klass->ext->nested_classes) {
4286 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4287 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4294 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4295 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4301 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4302 mono_error_raise_exception (&error); /* FIXME don't raise here */
4304 klass = mono_class_from_mono_type (t);
4306 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4308 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4309 parent_index, assembly);
4313 * We need to do this ourselves since klass->nested_classes is not set up.
4316 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4317 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4322 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4323 guint32 module_index, MonoDynamicImage *assembly)
4325 MonoImage *image = module->image;
4329 t = &image->tables [MONO_TABLE_TYPEDEF];
4331 for (i = 0; i < t->rows; ++i) {
4333 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4334 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4336 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4337 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4342 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4344 MonoDynamicTable *table;
4346 guint32 scope, scope_idx, impl, current_idx;
4347 gboolean forwarder = TRUE;
4348 gpointer iter = NULL;
4351 if (klass->nested_in) {
4352 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4355 scope = resolution_scope_from_image (assembly, klass->image);
4356 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4357 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4358 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4361 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4364 alloc_table (table, table->rows);
4365 current_idx = table->next_idx;
4366 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4368 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4369 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4370 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4371 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4372 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4376 while ((nested = mono_class_get_nested_types (klass, &iter)))
4377 add_exported_type (assemblyb, assembly, nested, current_idx);
4381 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4387 if (!assemblyb->type_forwarders)
4390 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4391 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4396 type = mono_reflection_type_get_handle (t, &error);
4397 mono_error_assert_ok (&error);
4400 klass = mono_class_from_mono_type (type);
4402 add_exported_type (assemblyb, assembly, klass, 0);
4406 #define align_pointer(base,p)\
4408 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4410 (p) += 4 - (__diff & 3);\
4414 compare_constants (const void *a, const void *b)
4416 const guint32 *a_values = (const guint32 *)a;
4417 const guint32 *b_values = (const guint32 *)b;
4418 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4422 compare_semantics (const void *a, const void *b)
4424 const guint32 *a_values = (const guint32 *)a;
4425 const guint32 *b_values = (const guint32 *)b;
4426 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4429 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4433 compare_custom_attrs (const void *a, const void *b)
4435 const guint32 *a_values = (const guint32 *)a;
4436 const guint32 *b_values = (const guint32 *)b;
4438 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4442 compare_field_marshal (const void *a, const void *b)
4444 const guint32 *a_values = (const guint32 *)a;
4445 const guint32 *b_values = (const guint32 *)b;
4447 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4451 compare_nested (const void *a, const void *b)
4453 const guint32 *a_values = (const guint32 *)a;
4454 const guint32 *b_values = (const guint32 *)b;
4456 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4460 compare_genericparam (const void *a, const void *b)
4463 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4464 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4466 if ((*b_entry)->owner == (*a_entry)->owner) {
4467 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4468 mono_error_assert_ok (&error);
4469 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4470 mono_error_assert_ok (&error);
4472 mono_type_get_generic_param_num (a_type) -
4473 mono_type_get_generic_param_num (b_type);
4475 return (*a_entry)->owner - (*b_entry)->owner;
4479 compare_declsecurity_attrs (const void *a, const void *b)
4481 const guint32 *a_values = (const guint32 *)a;
4482 const guint32 *b_values = (const guint32 *)b;
4484 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4488 compare_interface_impl (const void *a, const void *b)
4490 const guint32 *a_values = (const guint32 *)a;
4491 const guint32 *b_values = (const guint32 *)b;
4493 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4497 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4501 pad_heap (MonoDynamicStream *sh)
4503 if (sh->index & 3) {
4504 int sz = 4 - (sh->index & 3);
4505 memset (sh->data + sh->index, 0, sz);
4512 MonoDynamicStream *stream;
4516 * build_compressed_metadata() fills in the blob of data that represents the
4517 * raw metadata as it will be saved in the PE file. The five streams are output
4518 * and the metadata tables are comnpressed from the guint32 array representation,
4519 * to the compressed on-disk format.
4522 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4524 MonoDynamicTable *table;
4526 guint64 valid_mask = 0;
4527 guint64 sorted_mask;
4528 guint32 heapt_size = 0;
4529 guint32 meta_size = 256; /* allow for header and other stuff */
4530 guint32 table_offset;
4531 guint32 ntables = 0;
4537 struct StreamDesc stream_desc [5];
4539 mono_error_init (error);
4541 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4542 for (i = 0; i < assembly->gen_params->len; i++) {
4543 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4544 if (!write_generic_param_entry (assembly, entry, error))
4548 stream_desc [0].name = "#~";
4549 stream_desc [0].stream = &assembly->tstream;
4550 stream_desc [1].name = "#Strings";
4551 stream_desc [1].stream = &assembly->sheap;
4552 stream_desc [2].name = "#US";
4553 stream_desc [2].stream = &assembly->us;
4554 stream_desc [3].name = "#Blob";
4555 stream_desc [3].stream = &assembly->blob;
4556 stream_desc [4].name = "#GUID";
4557 stream_desc [4].stream = &assembly->guid;
4559 /* tables that are sorted */
4560 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4561 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4562 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4563 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4564 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4565 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4566 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4568 /* Compute table sizes */
4569 /* the MonoImage has already been created in mono_image_basic_init() */
4570 meta = &assembly->image;
4572 /* sizes should be multiple of 4 */
4573 pad_heap (&assembly->blob);
4574 pad_heap (&assembly->guid);
4575 pad_heap (&assembly->sheap);
4576 pad_heap (&assembly->us);
4578 /* Setup the info used by compute_sizes () */
4579 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4580 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4581 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4583 meta_size += assembly->blob.index;
4584 meta_size += assembly->guid.index;
4585 meta_size += assembly->sheap.index;
4586 meta_size += assembly->us.index;
4588 for (i=0; i < MONO_TABLE_NUM; ++i)
4589 meta->tables [i].rows = assembly->tables [i].rows;
4591 for (i = 0; i < MONO_TABLE_NUM; i++){
4592 if (meta->tables [i].rows == 0)
4594 valid_mask |= (guint64)1 << i;
4596 meta->tables [i].row_size = mono_metadata_compute_size (
4597 meta, i, &meta->tables [i].size_bitfield);
4598 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4600 heapt_size += 24; /* #~ header size */
4601 heapt_size += ntables * 4;
4602 /* make multiple of 4 */
4605 meta_size += heapt_size;
4606 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4607 p = (unsigned char*)meta->raw_metadata;
4608 /* the metadata signature */
4609 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4610 /* version numbers and 4 bytes reserved */
4611 int16val = (guint16*)p;
4612 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4613 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4615 /* version string */
4616 int32val = (guint32*)p;
4617 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4619 memcpy (p, meta->version, strlen (meta->version));
4620 p += GUINT32_FROM_LE (*int32val);
4621 align_pointer (meta->raw_metadata, p);
4622 int16val = (guint16*)p;
4623 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4624 *int16val = GUINT16_TO_LE (5); /* number of streams */
4628 * write the stream info.
4630 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4631 table_offset += 3; table_offset &= ~3;
4633 assembly->tstream.index = heapt_size;
4634 for (i = 0; i < 5; ++i) {
4635 int32val = (guint32*)p;
4636 stream_desc [i].stream->offset = table_offset;
4637 *int32val++ = GUINT32_TO_LE (table_offset);
4638 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4639 table_offset += GUINT32_FROM_LE (*int32val);
4640 table_offset += 3; table_offset &= ~3;
4642 strcpy ((char*)p, stream_desc [i].name);
4643 p += strlen (stream_desc [i].name) + 1;
4644 align_pointer (meta->raw_metadata, p);
4647 * now copy the data, the table stream header and contents goes first.
4649 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4650 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4651 int32val = (guint32*)p;
4652 *int32val = GUINT32_TO_LE (0); /* reserved */
4655 *p++ = 2; /* version */
4658 if (meta->idx_string_wide)
4660 if (meta->idx_guid_wide)
4662 if (meta->idx_blob_wide)
4665 *p++ = 1; /* reserved */
4666 int64val = (guint64*)p;
4667 *int64val++ = GUINT64_TO_LE (valid_mask);
4668 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4670 int32val = (guint32*)p;
4671 for (i = 0; i < MONO_TABLE_NUM; i++){
4672 if (meta->tables [i].rows == 0)
4674 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4676 p = (unsigned char*)int32val;
4678 /* sort the tables that still need sorting */
4679 table = &assembly->tables [MONO_TABLE_CONSTANT];
4681 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4682 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4684 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4685 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4687 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4688 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4690 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4691 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4693 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4694 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4695 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4697 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4698 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4700 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4702 /* compress the tables */
4703 for (i = 0; i < MONO_TABLE_NUM; i++){
4706 guint32 bitfield = meta->tables [i].size_bitfield;
4707 if (!meta->tables [i].rows)
4709 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4710 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4711 meta->tables [i].base = (char*)p;
4712 for (row = 1; row <= meta->tables [i].rows; ++row) {
4713 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4714 for (col = 0; col < assembly->tables [i].columns; ++col) {
4715 switch (mono_metadata_table_size (bitfield, col)) {
4717 *p++ = values [col];
4720 *p++ = values [col] & 0xff;
4721 *p++ = (values [col] >> 8) & 0xff;
4724 *p++ = values [col] & 0xff;
4725 *p++ = (values [col] >> 8) & 0xff;
4726 *p++ = (values [col] >> 16) & 0xff;
4727 *p++ = (values [col] >> 24) & 0xff;
4730 g_assert_not_reached ();
4734 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4737 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4738 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4739 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4740 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4741 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4743 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4749 * Some tables in metadata need to be sorted according to some criteria, but
4750 * when methods and fields are first created with reflection, they may be assigned a token
4751 * that doesn't correspond to the final token they will get assigned after the sorting.
4752 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4753 * with the reflection objects that represent them. Once all the tables are set up, the
4754 * reflection objects will contains the correct table index. fixup_method() will fixup the
4755 * tokens for the method with ILGenerator @ilgen.
4758 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4760 guint32 code_idx = GPOINTER_TO_UINT (value);
4761 MonoReflectionILTokenInfo *iltoken;
4762 MonoReflectionFieldBuilder *field;
4763 MonoReflectionCtorBuilder *ctor;
4764 MonoReflectionMethodBuilder *method;
4765 MonoReflectionTypeBuilder *tb;
4766 MonoReflectionArrayMethod *am;
4768 unsigned char *target;
4770 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4771 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4772 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4773 switch (target [3]) {
4774 case MONO_TABLE_FIELD:
4775 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4776 field = (MonoReflectionFieldBuilder *)iltoken->member;
4777 idx = field->table_idx;
4778 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4779 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4780 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4782 g_assert_not_reached ();
4785 case MONO_TABLE_METHOD:
4786 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4787 method = (MonoReflectionMethodBuilder *)iltoken->member;
4788 idx = method->table_idx;
4789 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4790 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4791 idx = ctor->table_idx;
4792 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4793 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4794 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4795 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4797 g_assert_not_reached ();
4800 case MONO_TABLE_TYPEDEF:
4801 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4802 g_assert_not_reached ();
4803 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4804 idx = tb->table_idx;
4806 case MONO_TABLE_MEMBERREF:
4807 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4808 am = (MonoReflectionArrayMethod*)iltoken->member;
4809 idx = am->table_idx;
4810 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4811 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4812 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4813 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4814 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4815 g_assert (m->klass->generic_class || m->klass->generic_container);
4817 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4819 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4820 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4821 g_assert (is_field_on_inst (f));
4823 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4824 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4826 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4828 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4830 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4833 g_assert_not_reached ();
4836 case MONO_TABLE_METHODSPEC:
4837 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4838 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4839 g_assert (mono_method_signature (m)->generic_param_count);
4841 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4843 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4846 g_assert_not_reached ();
4850 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4852 target [0] = idx & 0xff;
4853 target [1] = (idx >> 8) & 0xff;
4854 target [2] = (idx >> 16) & 0xff;
4861 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4862 * value is not known when the table is emitted.
4865 fixup_cattrs (MonoDynamicImage *assembly)
4867 MonoDynamicTable *table;
4869 guint32 type, i, idx, token;
4872 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4874 for (i = 0; i < table->rows; ++i) {
4875 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4877 type = values [MONO_CUSTOM_ATTR_TYPE];
4878 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4879 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4880 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4881 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4884 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4885 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4886 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4887 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4888 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4889 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4890 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4891 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4898 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4900 MonoDynamicTable *table;
4903 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4905 alloc_table (table, table->rows);
4906 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4907 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4908 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4909 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4910 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4915 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4917 MonoDynamicTable *table;
4921 char *b = blob_size;
4923 guint32 idx, offset;
4925 if (rsrc->filename) {
4926 name = mono_string_to_utf8 (rsrc->filename);
4927 sname = g_path_get_basename (name);
4929 table = &assembly->tables [MONO_TABLE_FILE];
4931 alloc_table (table, table->rows);
4932 values = table->values + table->next_idx * MONO_FILE_SIZE;
4933 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4934 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4937 mono_sha1_get_digest_from_file (name, hash);
4938 mono_metadata_encode_value (20, b, &b);
4939 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4940 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4942 idx = table->next_idx++;
4944 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4950 data = mono_array_addr (rsrc->data, char, 0);
4951 len = mono_array_length (rsrc->data);
4957 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4958 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4959 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4960 mono_image_add_stream_data (&assembly->resources, data, len);
4964 * The entry should be emitted into the MANIFESTRESOURCE table of
4965 * the main module, but that needs to reference the FILE table
4966 * which isn't emitted yet.
4973 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4977 set_version_from_string (MonoString *version, guint32 *values)
4979 gchar *ver, *p, *str;
4982 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4983 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4984 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4985 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4988 ver = str = mono_string_to_utf8 (version);
4989 for (i = 0; i < 4; ++i) {
4990 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4996 /* handle Revision and Build */
5006 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5010 char *b = blob_size;
5015 len = mono_array_length (pkey);
5016 mono_metadata_encode_value (len, b, &b);
5017 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5018 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5020 assembly->public_key = (guint8 *)g_malloc (len);
5021 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5022 assembly->public_key_len = len;
5024 /* Special case: check for ECMA key (16 bytes) */
5025 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5026 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5027 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5028 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5029 /* minimum key size (in 2.0) is 384 bits */
5030 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5032 /* FIXME - verifier */
5033 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5034 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5036 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5042 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5044 MonoDynamicTable *table;
5045 MonoDynamicImage *assembly;
5046 MonoReflectionAssemblyBuilder *assemblyb;
5050 guint32 module_index;
5052 assemblyb = moduleb->assemblyb;
5053 assembly = moduleb->dynamic_image;
5054 domain = mono_object_domain (assemblyb);
5056 /* Emit ASSEMBLY table */
5057 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5058 alloc_table (table, 1);
5059 values = table->values + MONO_ASSEMBLY_SIZE;
5060 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5061 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5062 if (assemblyb->culture) {
5063 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5065 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5067 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5068 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5069 set_version_from_string (assemblyb->version, values);
5071 /* Emit FILE + EXPORTED_TYPE table */
5073 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5075 MonoReflectionModuleBuilder *file_module =
5076 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5077 if (file_module != moduleb) {
5078 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5080 if (file_module->types) {
5081 for (j = 0; j < file_module->num_types; ++j) {
5082 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5083 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5088 if (assemblyb->loaded_modules) {
5089 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5090 MonoReflectionModule *file_module =
5091 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5092 mono_image_fill_file_table (domain, file_module, assembly);
5094 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5097 if (assemblyb->type_forwarders)
5098 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5100 /* Emit MANIFESTRESOURCE table */
5102 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5104 MonoReflectionModuleBuilder *file_module =
5105 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5106 /* The table for the main module is emitted later */
5107 if (file_module != moduleb) {
5109 if (file_module->resources) {
5110 int len = mono_array_length (file_module->resources);
5111 for (j = 0; j < len; ++j) {
5112 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5113 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5120 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5123 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5124 * for the modulebuilder @moduleb.
5125 * At the end of the process, method and field tokens are fixed up and the
5126 * on-disk compressed metadata representation is created.
5127 * Return TRUE on success, or FALSE on failure and sets @error
5130 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5132 MonoDynamicTable *table;
5133 MonoDynamicImage *assembly;
5134 MonoReflectionAssemblyBuilder *assemblyb;
5140 mono_error_init (error);
5142 assemblyb = moduleb->assemblyb;
5143 assembly = moduleb->dynamic_image;
5144 domain = mono_object_domain (assemblyb);
5146 if (assembly->text_rva)
5149 assembly->text_rva = START_TEXT_RVA;
5151 if (moduleb->is_main) {
5152 mono_image_emit_manifest (moduleb);
5155 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5156 table->rows = 1; /* .<Module> */
5158 alloc_table (table, table->rows);
5160 * Set the first entry.
5162 values = table->values + table->columns;
5163 values [MONO_TYPEDEF_FLAGS] = 0;
5164 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5165 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5166 values [MONO_TYPEDEF_EXTENDS] = 0;
5167 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5168 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5171 * handle global methods
5172 * FIXME: test what to do when global methods are defined in multiple modules.
5174 if (moduleb->global_methods) {
5175 table = &assembly->tables [MONO_TABLE_METHOD];
5176 table->rows += mono_array_length (moduleb->global_methods);
5177 alloc_table (table, table->rows);
5178 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5179 if (!mono_image_get_method_info (
5180 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5184 if (moduleb->global_fields) {
5185 table = &assembly->tables [MONO_TABLE_FIELD];
5186 table->rows += mono_array_length (moduleb->global_fields);
5187 alloc_table (table, table->rows);
5188 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5189 mono_image_get_field_info (
5190 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5197 table = &assembly->tables [MONO_TABLE_MODULE];
5198 alloc_table (table, 1);
5199 mono_image_fill_module_table (domain, moduleb, assembly);
5201 /* Collect all types into a list sorted by their table_idx */
5202 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5205 for (i = 0; i < moduleb->num_types; ++i) {
5206 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5207 collect_types (&types, type);
5210 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5211 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5212 table->rows += mono_ptr_array_size (types);
5213 alloc_table (table, table->rows);
5216 * Emit type names + namespaces at one place inside the string heap,
5217 * so load_class_names () needs to touch fewer pages.
5219 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5220 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5221 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5223 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5224 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5225 string_heap_insert_mstring (&assembly->sheap, tb->name);
5228 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5229 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5230 if (!mono_image_get_type_info (domain, type, assembly, error))
5235 * table->rows is already set above and in mono_image_fill_module_table.
5237 /* add all the custom attributes at the end, once all the indexes are stable */
5238 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5241 /* CAS assembly permissions */
5242 if (assemblyb->permissions_minimum)
5243 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5244 if (assemblyb->permissions_optional)
5245 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5246 if (assemblyb->permissions_refused)
5247 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5249 if (!module_add_cattrs (assembly, moduleb, error))
5253 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5255 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5256 * the final tokens and don't need another fixup pass. */
5258 if (moduleb->global_methods) {
5259 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5260 MonoReflectionMethodBuilder *mb = mono_array_get (
5261 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5262 if (!mono_image_add_methodimpl (assembly, mb, error))
5267 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5268 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5269 if (type->methods) {
5270 for (j = 0; j < type->num_methods; ++j) {
5271 MonoReflectionMethodBuilder *mb = mono_array_get (
5272 type->methods, MonoReflectionMethodBuilder*, j);
5274 if (!mono_image_add_methodimpl (assembly, mb, error))
5280 fixup_cattrs (assembly);
5283 mono_ptr_array_destroy (types);
5286 return mono_error_ok (error);
5289 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5292 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5294 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5297 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5301 guint32 import_lookup_table;
5305 guint32 import_address_table_rva;
5313 #ifndef DISABLE_REFLECTION_EMIT
5316 * mono_image_insert_string:
5317 * @module: module builder object
5320 * Insert @str into the user string stream of @module.
5323 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5325 MonoDynamicImage *assembly;
5330 if (!module->dynamic_image)
5331 mono_image_module_basic_init (module);
5333 assembly = module->dynamic_image;
5335 if (assembly->save) {
5336 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5337 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5338 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5340 char *swapped = g_malloc (2 * mono_string_length (str));
5341 const char *p = (const char*)mono_string_chars (str);
5343 swap_with_size (swapped, p, 2, mono_string_length (str));
5344 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5348 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5350 mono_image_add_stream_data (&assembly->us, "", 1);
5352 idx = assembly->us.index ++;
5355 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5357 return MONO_TOKEN_STRING | idx;
5361 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5365 MonoMethodSignature *sig;
5367 mono_error_init (error);
5369 klass = obj->vtable->klass;
5370 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5371 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5372 MonoMethodSignature *old;
5373 guint32 sig_token, parent;
5376 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5378 nargs = mono_array_length (opt_param_types);
5379 old = mono_method_signature (method);
5380 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5382 sig->hasthis = old->hasthis;
5383 sig->explicit_this = old->explicit_this;
5384 sig->call_convention = old->call_convention;
5385 sig->generic_param_count = old->generic_param_count;
5386 sig->param_count = old->param_count + nargs;
5387 sig->sentinelpos = old->param_count;
5388 sig->ret = old->ret;
5390 for (i = 0; i < old->param_count; i++)
5391 sig->params [i] = old->params [i];
5393 for (i = 0; i < nargs; i++) {
5394 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5395 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5396 if (!is_ok (error)) goto fail;
5399 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5400 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5401 parent >>= MONO_TYPEDEFORREF_BITS;
5403 parent <<= MONO_MEMBERREF_PARENT_BITS;
5404 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5406 sig_token = method_encode_signature (assembly, sig);
5407 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5408 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5409 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5410 ReflectionMethodBuilder rmb;
5411 guint32 parent, sig_token;
5412 int nopt_args, nparams, ngparams, i;
5414 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5417 rmb.opt_types = opt_param_types;
5418 nopt_args = mono_array_length (opt_param_types);
5420 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5421 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5422 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5424 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5425 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5426 sig->call_convention = rmb.call_conv;
5427 sig->generic_param_count = ngparams;
5428 sig->param_count = nparams + nopt_args;
5429 sig->sentinelpos = nparams;
5430 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5431 if (!is_ok (error)) goto fail;
5433 for (i = 0; i < nparams; i++) {
5434 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5435 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5436 if (!is_ok (error)) goto fail;
5439 for (i = 0; i < nopt_args; i++) {
5440 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5441 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5442 if (!is_ok (error)) goto fail;
5445 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5449 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5450 if (!mono_error_ok (error))
5452 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5454 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5455 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5457 char *name = mono_string_to_utf8 (rmb.name);
5458 token = mono_image_get_varargs_method_token (
5459 assembly, parent, name, sig_token);
5462 g_error ("requested method token for %s\n", klass->name);
5465 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5466 register_dyn_token (assembly, token, obj);
5469 g_assert (!mono_error_ok (error));
5474 * mono_image_create_token:
5475 * @assembly: a dynamic assembly
5477 * @register_token: Whenever to register the token in the assembly->tokens hash.
5479 * Get a token to insert in the IL code stream for the given MemberInfo.
5480 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5481 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5485 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5486 gboolean create_open_instance, gboolean register_token,
5492 mono_error_init (error);
5494 klass = obj->vtable->klass;
5496 /* Check for user defined reflection objects */
5497 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5498 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5499 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5503 if (strcmp (klass->name, "MethodBuilder") == 0) {
5504 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5505 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5507 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5508 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5510 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5511 if (!mono_error_ok (error))
5514 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5515 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5516 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5517 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5519 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5520 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5522 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5523 if (!mono_error_ok (error))
5526 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5527 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5528 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5529 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5530 if (tb->generic_params) {
5531 token = mono_image_get_generic_field_token (assembly, fb);
5533 if (tb->module->dynamic_image == assembly) {
5534 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5536 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5539 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5540 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5541 if (create_open_instance && tb->generic_params) {
5543 init_type_builder_generics (obj);
5544 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5545 return_val_if_nok (error, 0);
5546 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5547 token = mono_metadata_token_from_dor (token);
5548 } else if (tb->module->dynamic_image == assembly) {
5549 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5552 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5553 return_val_if_nok (error, 0);
5554 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5556 } else if (strcmp (klass->name, "MonoType") == 0) {
5557 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5558 return_val_if_nok (error, 0);
5559 MonoClass *mc = mono_class_from_mono_type (type);
5560 token = mono_metadata_token_from_dor (
5561 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5562 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5563 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5564 return_val_if_nok (error, 0);
5565 token = mono_metadata_token_from_dor (
5566 mono_image_typedef_or_ref (assembly, type));
5567 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5568 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5569 return_val_if_nok (error, 0);
5570 token = mono_metadata_token_from_dor (
5571 mono_image_typedef_or_ref (assembly, type));
5572 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5573 strcmp (klass->name, "MonoMethod") == 0 ||
5574 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5575 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5576 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5577 if (m->method->is_inflated) {
5578 if (create_open_instance)
5579 token = mono_image_get_methodspec_token (assembly, m->method);
5581 token = mono_image_get_inflated_method_token (assembly, m->method);
5582 } else if ((m->method->klass->image == &assembly->image) &&
5583 !m->method->klass->generic_class) {
5584 static guint32 method_table_idx = 0xffffff;
5585 if (m->method->klass->wastypebuilder) {
5586 /* we use the same token as the one that was assigned
5587 * to the Methodbuilder.
5588 * FIXME: do the equivalent for Fields.
5590 token = m->method->token;
5593 * Each token should have a unique index, but the indexes are
5594 * assigned by managed code, so we don't know about them. An
5595 * easy solution is to count backwards...
5597 method_table_idx --;
5598 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5601 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5603 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5604 } else if (strcmp (klass->name, "MonoField") == 0) {
5605 MonoReflectionField *f = (MonoReflectionField *)obj;
5606 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5607 static guint32 field_table_idx = 0xffffff;
5609 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5611 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5613 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5614 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5615 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5616 token = mono_image_get_array_token (assembly, m);
5617 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5618 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5619 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5620 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5621 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5622 return_val_if_nok (error, 0);
5623 token = mono_metadata_token_from_dor (
5624 mono_image_typedef_or_ref (assembly, type));
5625 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5626 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5627 token = mono_image_get_field_on_inst_token (assembly, f, error);
5628 return_val_if_nok (error, 0);
5629 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5630 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5631 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5632 if (!mono_error_ok (error))
5634 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5635 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5636 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5637 if (!mono_error_ok (error))
5639 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5640 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5641 return_val_if_nok (error, 0);
5642 token = mono_metadata_token_from_dor (
5643 mono_image_typedef_or_ref (assembly, type));
5645 g_error ("requested token for %s\n", klass->name);
5649 mono_image_register_token (assembly, token, obj);
5655 * mono_image_register_token:
5657 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5658 * the Module.ResolveXXXToken () methods to work.
5661 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5665 dynamic_image_lock (assembly);
5666 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5668 /* There could be multiple MethodInfo objects with the same token */
5669 //g_assert (prev == obj);
5671 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5673 dynamic_image_unlock (assembly);
5676 static MonoDynamicImage*
5677 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5679 static const guchar entrycode [16] = {0xff, 0x25, 0};
5680 MonoDynamicImage *image;
5683 const char *version;
5685 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5686 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5688 version = mono_get_runtime_info ()->runtime_version;
5691 /* The MonoGHashTable's need GC tracking */
5692 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5694 image = g_new0 (MonoDynamicImage, 1);
5697 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5699 /*g_print ("created image %p\n", image);*/
5700 /* keep in sync with image.c */
5701 image->image.name = assembly_name;
5702 image->image.assembly_name = image->image.name; /* they may be different */
5703 image->image.module_name = module_name;
5704 image->image.version = g_strdup (version);
5705 image->image.md_version_major = 1;
5706 image->image.md_version_minor = 1;
5707 image->image.dynamic = TRUE;
5709 image->image.references = g_new0 (MonoAssembly*, 1);
5710 image->image.references [0] = NULL;
5712 mono_image_init (&image->image);
5714 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");
5715 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5716 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5717 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5718 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5719 image->handleref = g_hash_table_new (NULL, NULL);
5720 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");
5721 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5722 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");
5723 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");
5724 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5725 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5726 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5727 image->gen_params = g_ptr_array_new ();
5728 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5730 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5731 string_heap_init (&image->sheap);
5732 mono_image_add_stream_data (&image->us, "", 1);
5733 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5734 /* import tables... */
5735 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5736 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5737 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5738 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5739 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5740 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5741 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5742 stream_data_align (&image->code);
5744 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5746 for (i=0; i < MONO_TABLE_NUM; ++i) {
5747 image->tables [i].next_idx = 1;
5748 image->tables [i].columns = table_sizes [i];
5751 image->image.assembly = (MonoAssembly*)assembly;
5752 image->run = assembly->run;
5753 image->save = assembly->save;
5754 image->pe_kind = 0x1; /* ILOnly */
5755 image->machine = 0x14c; /* I386 */
5757 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5759 dynamic_images_lock ();
5761 if (!dynamic_images)
5762 dynamic_images = g_ptr_array_new ();
5764 g_ptr_array_add (dynamic_images, image);
5766 dynamic_images_unlock ();
5773 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5779 release_hashtable (MonoGHashTable **hash)
5782 mono_g_hash_table_destroy (*hash);
5788 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5790 release_hashtable (&image->token_fixups);
5791 release_hashtable (&image->handleref_managed);
5792 release_hashtable (&image->tokens);
5793 release_hashtable (&image->remapped_tokens);
5794 release_hashtable (&image->generic_def_objects);
5795 release_hashtable (&image->methodspec);
5798 // Free dynamic image pass one: Free resources but not image itself
5800 mono_dynamic_image_free (MonoDynamicImage *image)
5802 MonoDynamicImage *di = image;
5807 mono_g_hash_table_destroy (di->methodspec);
5809 g_hash_table_destroy (di->typespec);
5811 g_hash_table_destroy (di->typeref);
5813 g_hash_table_destroy (di->handleref);
5814 if (di->handleref_managed)
5815 mono_g_hash_table_destroy (di->handleref_managed);
5817 mono_g_hash_table_destroy (di->tokens);
5818 if (di->remapped_tokens)
5819 mono_g_hash_table_destroy (di->remapped_tokens);
5820 if (di->generic_def_objects)
5821 mono_g_hash_table_destroy (di->generic_def_objects);
5822 if (di->blob_cache) {
5823 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5824 g_hash_table_destroy (di->blob_cache);
5826 if (di->standalonesig_cache)
5827 g_hash_table_destroy (di->standalonesig_cache);
5828 for (list = di->array_methods; list; list = list->next) {
5829 ArrayMethod *am = (ArrayMethod *)list->data;
5834 g_list_free (di->array_methods);
5835 if (di->gen_params) {
5836 for (i = 0; i < di->gen_params->len; i++) {
5837 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5838 mono_gc_deregister_root ((char*) &entry->gparam);
5841 g_ptr_array_free (di->gen_params, TRUE);
5843 if (di->token_fixups)
5844 mono_g_hash_table_destroy (di->token_fixups);
5845 if (di->method_to_table_idx)
5846 g_hash_table_destroy (di->method_to_table_idx);
5847 if (di->field_to_table_idx)
5848 g_hash_table_destroy (di->field_to_table_idx);
5849 if (di->method_aux_hash)
5850 g_hash_table_destroy (di->method_aux_hash);
5851 if (di->vararg_aux_hash)
5852 g_hash_table_destroy (di->vararg_aux_hash);
5853 g_free (di->strong_name);
5854 g_free (di->win32_res);
5856 g_free (di->public_key);
5858 /*g_print ("string heap destroy for image %p\n", di);*/
5859 mono_dynamic_stream_reset (&di->sheap);
5860 mono_dynamic_stream_reset (&di->code);
5861 mono_dynamic_stream_reset (&di->resources);
5862 mono_dynamic_stream_reset (&di->us);
5863 mono_dynamic_stream_reset (&di->blob);
5864 mono_dynamic_stream_reset (&di->tstream);
5865 mono_dynamic_stream_reset (&di->guid);
5866 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5867 g_free (di->tables [i].values);
5870 dynamic_images_lock ();
5873 g_ptr_array_remove (dynamic_images, di);
5875 dynamic_images_unlock ();
5878 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5880 mono_dynamic_image_free_image (MonoDynamicImage *image)
5882 /* See create_dynamic_mono_image () */
5884 /* Allocated using GC_MALLOC */
5890 #ifndef DISABLE_REFLECTION_EMIT
5893 * mono_image_basic_init:
5894 * @assembly: an assembly builder object
5896 * Create the MonoImage that represents the assembly builder and setup some
5897 * of the helper hash table and the basic metadata streams.
5900 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5902 MonoDynamicAssembly *assembly;
5903 MonoDynamicImage *image;
5904 MonoDomain *domain = mono_object_domain (assemblyb);
5906 if (assemblyb->dynamic_assembly)
5910 /* assembly->assembly.image might be GC allocated */
5911 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5913 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5916 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5918 assembly->assembly.ref_count = 1;
5919 assembly->assembly.dynamic = TRUE;
5920 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5921 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5922 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5923 if (assemblyb->culture)
5924 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5926 assembly->assembly.aname.culture = g_strdup ("");
5928 if (assemblyb->version) {
5929 char *vstr = mono_string_to_utf8 (assemblyb->version);
5930 char **version = g_strsplit (vstr, ".", 4);
5931 char **parts = version;
5932 assembly->assembly.aname.major = atoi (*parts++);
5933 assembly->assembly.aname.minor = atoi (*parts++);
5934 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5935 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5937 g_strfreev (version);
5940 assembly->assembly.aname.major = 0;
5941 assembly->assembly.aname.minor = 0;
5942 assembly->assembly.aname.build = 0;
5943 assembly->assembly.aname.revision = 0;
5946 assembly->run = assemblyb->access != 2;
5947 assembly->save = assemblyb->access != 1;
5948 assembly->domain = domain;
5950 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5951 image->initial_image = TRUE;
5952 assembly->assembly.aname.name = image->image.name;
5953 assembly->assembly.image = &image->image;
5954 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5955 /* -1 to correct for the trailing NULL byte */
5956 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5957 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5959 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5962 mono_domain_assemblies_lock (domain);
5963 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5964 mono_domain_assemblies_unlock (domain);
5966 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5968 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5970 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5973 #endif /* !DISABLE_REFLECTION_EMIT */
5975 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5978 calc_section_size (MonoDynamicImage *assembly)
5982 /* alignment constraints */
5983 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5984 g_assert ((assembly->code.index % 4) == 0);
5985 assembly->meta_size += 3;
5986 assembly->meta_size &= ~3;
5987 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5988 g_assert ((assembly->resources.index % 4) == 0);
5990 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5991 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5994 if (assembly->win32_res) {
5995 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5997 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5998 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6002 assembly->sections [MONO_SECTION_RELOC].size = 12;
6003 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6013 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6017 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6019 ResTreeNode *t1 = (ResTreeNode*)a;
6020 ResTreeNode *t2 = (ResTreeNode*)b;
6022 return t1->id - t2->id;
6026 * resource_tree_create:
6028 * Organize the resources into a resource tree.
6030 static ResTreeNode *
6031 resource_tree_create (MonoArray *win32_resources)
6033 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6037 tree = g_new0 (ResTreeNode, 1);
6039 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6040 MonoReflectionWin32Resource *win32_res =
6041 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6045 /* FIXME: BUG: this stores managed references in unmanaged memory */
6046 lang_node = g_new0 (ResTreeNode, 1);
6047 lang_node->id = win32_res->lang_id;
6048 lang_node->win32_res = win32_res;
6050 /* Create type node if neccesary */
6052 for (l = tree->children; l; l = l->next)
6053 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6054 type_node = (ResTreeNode*)l->data;
6059 type_node = g_new0 (ResTreeNode, 1);
6060 type_node->id = win32_res->res_type;
6063 * The resource types have to be sorted otherwise
6064 * Windows Explorer can't display the version information.
6066 tree->children = g_slist_insert_sorted (tree->children,
6067 type_node, resource_tree_compare_by_id);
6070 /* Create res node if neccesary */
6072 for (l = type_node->children; l; l = l->next)
6073 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6074 res_node = (ResTreeNode*)l->data;
6079 res_node = g_new0 (ResTreeNode, 1);
6080 res_node->id = win32_res->res_id;
6081 type_node->children = g_slist_append (type_node->children, res_node);
6084 res_node->children = g_slist_append (res_node->children, lang_node);
6091 * resource_tree_encode:
6093 * Encode the resource tree into the format used in the PE file.
6096 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6099 MonoPEResourceDir dir;
6100 MonoPEResourceDirEntry dir_entry;
6101 MonoPEResourceDataEntry data_entry;
6103 guint32 res_id_entries;
6106 * For the format of the resource directory, see the article
6107 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6111 memset (&dir, 0, sizeof (dir));
6112 memset (&dir_entry, 0, sizeof (dir_entry));
6113 memset (&data_entry, 0, sizeof (data_entry));
6115 g_assert (sizeof (dir) == 16);
6116 g_assert (sizeof (dir_entry) == 8);
6117 g_assert (sizeof (data_entry) == 16);
6119 node->offset = p - begin;
6121 /* IMAGE_RESOURCE_DIRECTORY */
6122 res_id_entries = g_slist_length (node->children);
6123 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6125 memcpy (p, &dir, sizeof (dir));
6128 /* Reserve space for entries */
6130 p += sizeof (dir_entry) * res_id_entries;
6132 /* Write children */
6133 for (l = node->children; l; l = l->next) {
6134 ResTreeNode *child = (ResTreeNode*)l->data;
6136 if (child->win32_res) {
6139 child->offset = p - begin;
6141 /* IMAGE_RESOURCE_DATA_ENTRY */
6142 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6143 size = mono_array_length (child->win32_res->res_data);
6144 data_entry.rde_size = GUINT32_TO_LE (size);
6146 memcpy (p, &data_entry, sizeof (data_entry));
6147 p += sizeof (data_entry);
6149 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6152 resource_tree_encode (child, begin, p, &p);
6156 /* IMAGE_RESOURCE_ENTRY */
6157 for (l = node->children; l; l = l->next) {
6158 ResTreeNode *child = (ResTreeNode*)l->data;
6160 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6161 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6163 memcpy (entries, &dir_entry, sizeof (dir_entry));
6164 entries += sizeof (dir_entry);
6171 resource_tree_free (ResTreeNode * node)
6174 for (list = node->children; list; list = list->next)
6175 resource_tree_free ((ResTreeNode*)list->data);
6176 g_slist_free(node->children);
6181 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6186 MonoReflectionWin32Resource *win32_res;
6189 if (!assemblyb->win32_resources)
6193 * Resources are stored in a three level tree inside the PE file.
6194 * - level one contains a node for each type of resource
6195 * - level two contains a node for each resource
6196 * - level three contains a node for each instance of a resource for a
6197 * specific language.
6200 tree = resource_tree_create (assemblyb->win32_resources);
6202 /* Estimate the size of the encoded tree */
6204 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6205 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6206 size += mono_array_length (win32_res->res_data);
6208 /* Directory structure */
6209 size += mono_array_length (assemblyb->win32_resources) * 256;
6210 p = buf = (char *)g_malloc (size);
6212 resource_tree_encode (tree, p, p, &p);
6214 g_assert (p - buf <= size);
6216 assembly->win32_res = (char *)g_malloc (p - buf);
6217 assembly->win32_res_size = p - buf;
6218 memcpy (assembly->win32_res, buf, p - buf);
6221 resource_tree_free (tree);
6225 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6227 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6230 p += sizeof (MonoPEResourceDir);
6231 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6232 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6233 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6234 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6235 fixup_resource_directory (res_section, child, rva);
6237 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6238 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6241 p += sizeof (MonoPEResourceDirEntry);
6246 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6249 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6250 g_error ("WriteFile returned %d\n", GetLastError ());
6254 * mono_image_create_pefile:
6255 * @mb: a module builder object
6257 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6258 * assembly->pefile where it can be easily retrieved later in chunks.
6261 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6263 MonoMSDOSHeader *msdos;
6264 MonoDotNetHeader *header;
6265 MonoSectionTable *section;
6266 MonoCLIHeader *cli_header;
6267 guint32 size, image_size, virtual_base, text_offset;
6268 guint32 header_start, section_start, file_offset, virtual_offset;
6269 MonoDynamicImage *assembly;
6270 MonoReflectionAssemblyBuilder *assemblyb;
6271 MonoDynamicStream pefile_stream = {0};
6272 MonoDynamicStream *pefile = &pefile_stream;
6274 guint32 *rva, value;
6276 static const unsigned char msheader[] = {
6277 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6278 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6281 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6282 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6283 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6284 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6287 mono_error_init (error);
6289 assemblyb = mb->assemblyb;
6291 mono_image_basic_init (assemblyb);
6292 assembly = mb->dynamic_image;
6294 assembly->pe_kind = assemblyb->pe_kind;
6295 assembly->machine = assemblyb->machine;
6296 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6297 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6299 if (!mono_image_build_metadata (mb, error))
6303 if (mb->is_main && assemblyb->resources) {
6304 int len = mono_array_length (assemblyb->resources);
6305 for (i = 0; i < len; ++i)
6306 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6309 if (mb->resources) {
6310 int len = mono_array_length (mb->resources);
6311 for (i = 0; i < len; ++i)
6312 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6315 if (!build_compressed_metadata (assembly, error))
6319 assembly_add_win32_resources (assembly, assemblyb);
6321 nsections = calc_section_size (assembly);
6323 /* The DOS header and stub */
6324 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6325 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6327 /* the dotnet header */
6328 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6330 /* the section tables */
6331 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6333 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6334 virtual_offset = VIRT_ALIGN;
6337 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6338 if (!assembly->sections [i].size)
6341 file_offset += FILE_ALIGN - 1;
6342 file_offset &= ~(FILE_ALIGN - 1);
6343 virtual_offset += VIRT_ALIGN - 1;
6344 virtual_offset &= ~(VIRT_ALIGN - 1);
6346 assembly->sections [i].offset = file_offset;
6347 assembly->sections [i].rva = virtual_offset;
6349 file_offset += assembly->sections [i].size;
6350 virtual_offset += assembly->sections [i].size;
6351 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6354 file_offset += FILE_ALIGN - 1;
6355 file_offset &= ~(FILE_ALIGN - 1);
6357 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6359 /* back-patch info */
6360 msdos = (MonoMSDOSHeader*)pefile->data;
6361 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6363 header = (MonoDotNetHeader*)(pefile->data + header_start);
6364 header->pesig [0] = 'P';
6365 header->pesig [1] = 'E';
6367 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6368 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6369 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6370 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6371 if (assemblyb->pekind == 1) {
6373 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6376 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6379 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6381 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6382 header->pe.pe_major = 6;
6383 header->pe.pe_minor = 0;
6384 size = assembly->sections [MONO_SECTION_TEXT].size;
6385 size += FILE_ALIGN - 1;
6386 size &= ~(FILE_ALIGN - 1);
6387 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6388 size = assembly->sections [MONO_SECTION_RSRC].size;
6389 size += FILE_ALIGN - 1;
6390 size &= ~(FILE_ALIGN - 1);
6391 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6392 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6393 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6394 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6395 /* pe_rva_entry_point always at the beginning of the text section */
6396 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6398 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6399 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6400 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6401 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6402 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6403 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6404 size = section_start;
6405 size += FILE_ALIGN - 1;
6406 size &= ~(FILE_ALIGN - 1);
6407 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6409 size += VIRT_ALIGN - 1;
6410 size &= ~(VIRT_ALIGN - 1);
6411 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6414 // Translate the PEFileKind value to the value expected by the Windows loader
6420 // PEFileKinds.Dll == 1
6421 // PEFileKinds.ConsoleApplication == 2
6422 // PEFileKinds.WindowApplication == 3
6425 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6426 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6428 if (assemblyb->pekind == 3)
6433 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6435 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6436 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6437 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6438 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6439 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6440 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6442 /* fill data directory entries */
6444 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6445 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6447 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6448 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6450 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6451 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6452 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6453 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6454 /* patch entrypoint name */
6455 if (assemblyb->pekind == 1)
6456 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6458 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6459 /* patch imported function RVA name */
6460 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6461 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6463 /* the import table */
6464 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6465 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6466 /* patch imported dll RVA name and other entries in the dir */
6467 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6468 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6469 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6470 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6471 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6472 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6474 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6475 value = (assembly->text_rva + assembly->imp_names_offset);
6476 *p++ = (value) & 0xff;
6477 *p++ = (value >> 8) & (0xff);
6478 *p++ = (value >> 16) & (0xff);
6479 *p++ = (value >> 24) & (0xff);
6481 /* the CLI header info */
6482 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6483 cli_header->ch_size = GUINT32_FROM_LE (72);
6484 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6485 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6486 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6487 if (assemblyb->entry_point) {
6488 guint32 table_idx = 0;
6489 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6490 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6491 table_idx = methodb->table_idx;
6493 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6495 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6497 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6499 /* The embedded managed resources */
6500 text_offset = assembly->text_rva + assembly->code.index;
6501 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6502 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6503 text_offset += assembly->resources.index;
6504 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6505 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6506 text_offset += assembly->meta_size;
6507 if (assembly->strong_name_size) {
6508 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6509 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6510 text_offset += assembly->strong_name_size;
6513 /* write the section tables and section content */
6514 section = (MonoSectionTable*)(pefile->data + section_start);
6515 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6516 static const char section_names [][7] = {
6517 ".text", ".rsrc", ".reloc"
6519 if (!assembly->sections [i].size)
6521 strcpy (section->st_name, section_names [i]);
6522 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6523 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6524 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6525 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6526 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6527 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6528 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6532 checked_write_file (file, pefile->data, pefile->index);
6534 mono_dynamic_stream_reset (pefile);
6536 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6537 if (!assembly->sections [i].size)
6540 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6541 g_error ("SetFilePointer returned %d\n", GetLastError ());
6544 case MONO_SECTION_TEXT:
6545 /* patch entry point */
6546 p = (guchar*)(assembly->code.data + 2);
6547 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6548 *p++ = (value) & 0xff;
6549 *p++ = (value >> 8) & 0xff;
6550 *p++ = (value >> 16) & 0xff;
6551 *p++ = (value >> 24) & 0xff;
6553 checked_write_file (file, assembly->code.data, assembly->code.index);
6554 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6555 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6556 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6559 g_free (assembly->image.raw_metadata);
6561 case MONO_SECTION_RELOC: {
6565 guint16 type_and_offset;
6569 g_assert (sizeof (reloc) == 12);
6571 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6572 reloc.block_size = GUINT32_FROM_LE (12);
6575 * the entrypoint is always at the start of the text section
6576 * 3 is IMAGE_REL_BASED_HIGHLOW
6577 * 2 is patch_size_rva - text_rva
6579 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6582 checked_write_file (file, &reloc, sizeof (reloc));
6586 case MONO_SECTION_RSRC:
6587 if (assembly->win32_res) {
6589 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6590 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6591 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6595 g_assert_not_reached ();
6599 /* check that the file is properly padded */
6600 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6601 g_error ("SetFilePointer returned %d\n", GetLastError ());
6602 if (! SetEndOfFile (file))
6603 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6605 mono_dynamic_stream_reset (&assembly->code);
6606 mono_dynamic_stream_reset (&assembly->us);
6607 mono_dynamic_stream_reset (&assembly->blob);
6608 mono_dynamic_stream_reset (&assembly->guid);
6609 mono_dynamic_stream_reset (&assembly->sheap);
6611 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6612 g_hash_table_destroy (assembly->blob_cache);
6613 assembly->blob_cache = NULL;
6618 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6621 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6623 g_assert_not_reached ();
6626 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6628 #ifndef DISABLE_REFLECTION_EMIT
6630 MonoReflectionModule *
6631 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6634 MonoReflectionModule *result = NULL;
6637 MonoImageOpenStatus status;
6638 MonoDynamicAssembly *assembly;
6639 guint32 module_count;
6640 MonoImage **new_modules;
6641 gboolean *new_modules_loaded;
6643 name = mono_string_to_utf8 (fileName);
6645 image = mono_image_open (name, &status);
6648 if (status == MONO_IMAGE_ERROR_ERRNO)
6649 exc = mono_get_exception_file_not_found (fileName);
6651 exc = mono_get_exception_bad_image_format (name);
6653 mono_raise_exception (exc);
6658 assembly = ab->dynamic_assembly;
6659 image->assembly = (MonoAssembly*)assembly;
6661 module_count = image->assembly->image->module_count;
6662 new_modules = g_new0 (MonoImage *, module_count + 1);
6663 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6665 if (image->assembly->image->modules)
6666 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6667 if (image->assembly->image->modules_loaded)
6668 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6669 new_modules [module_count] = image;
6670 new_modules_loaded [module_count] = TRUE;
6671 mono_image_addref (image);
6673 g_free (image->assembly->image->modules);
6674 image->assembly->image->modules = new_modules;
6675 image->assembly->image->modules_loaded = new_modules_loaded;
6676 image->assembly->image->module_count ++;
6678 mono_assembly_load_references (image, &status);
6680 mono_image_close (image);
6681 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6684 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6685 mono_error_raise_exception (&error); /* FIXME don't raise here */
6689 #endif /* DISABLE_REFLECTION_EMIT */
6692 * We need to return always the same object for MethodInfo, FieldInfo etc..
6693 * but we need to consider the reflected type.
6694 * type uses a different hash, since it uses custom hash/equal functions.
6699 MonoClass *refclass;
6703 reflected_equal (gconstpointer a, gconstpointer b) {
6704 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6705 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6707 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6711 reflected_hash (gconstpointer a) {
6712 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6713 return mono_aligned_addr_hash (ea->item);
6716 #define CHECK_OBJECT(t,p,k) \
6722 mono_domain_lock (domain); \
6723 if (!domain->refobject_hash) \
6724 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"); \
6725 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6726 mono_domain_unlock (domain); \
6729 mono_domain_unlock (domain); \
6732 #ifdef HAVE_BOEHM_GC
6733 /* ReflectedEntry doesn't need to be GC tracked */
6734 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6735 #define FREE_REFENTRY(entry) g_free ((entry))
6736 #define REFENTRY_REQUIRES_CLEANUP
6738 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6740 #define FREE_REFENTRY(entry)
6743 #define CACHE_OBJECT(t,p,o,k) \
6746 ReflectedEntry pe; \
6748 pe.refclass = (k); \
6749 mono_domain_lock (domain); \
6750 if (!domain->refobject_hash) \
6751 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"); \
6752 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6754 ReflectedEntry *e = ALLOC_REFENTRY; \
6756 e->refclass = (k); \
6757 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6760 mono_domain_unlock (domain); \
6765 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6767 mono_domain_lock (domain);
6768 if (domain->refobject_hash) {
6770 gpointer orig_pe, orig_value;
6773 pe.refclass = klass;
6774 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6775 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6776 FREE_REFENTRY (orig_pe);
6779 mono_domain_unlock (domain);
6782 #ifdef REFENTRY_REQUIRES_CLEANUP
6784 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6786 FREE_REFENTRY (key);
6791 mono_reflection_cleanup_domain (MonoDomain *domain)
6793 if (domain->refobject_hash) {
6794 /*let's avoid scanning the whole hashtable if not needed*/
6795 #ifdef REFENTRY_REQUIRES_CLEANUP
6796 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6798 mono_g_hash_table_destroy (domain->refobject_hash);
6799 domain->refobject_hash = NULL;
6803 #ifndef DISABLE_REFLECTION_EMIT
6805 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6807 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6811 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6813 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6817 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6819 MonoDynamicImage *image = moduleb->dynamic_image;
6820 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6824 MonoImage **new_modules;
6826 char *name, *fqname;
6828 * FIXME: we already created an image in mono_image_basic_init (), but
6829 * we don't know which module it belongs to, since that is only
6830 * determined at assembly save time.
6832 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6833 name = mono_string_to_utf8 (ab->name);
6834 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6835 if (!mono_error_ok (&error)) {
6837 mono_error_raise_exception (&error);
6839 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6841 moduleb->module.image = &image->image;
6842 moduleb->dynamic_image = image;
6843 register_module (mono_object_domain (moduleb), moduleb, image);
6845 /* register the module with the assembly */
6846 ass = ab->dynamic_assembly->assembly.image;
6847 module_count = ass->module_count;
6848 new_modules = g_new0 (MonoImage *, module_count + 1);
6851 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6852 new_modules [module_count] = &image->image;
6853 mono_image_addref (&image->image);
6855 g_free (ass->modules);
6856 ass->modules = new_modules;
6857 ass->module_count ++;
6862 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6864 MonoDynamicImage *image = moduleb->dynamic_image;
6866 g_assert (type->type);
6867 image->wrappers_type = mono_class_from_mono_type (type->type);
6873 * mono_assembly_get_object:
6874 * @domain: an app domain
6875 * @assembly: an assembly
6877 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6879 MonoReflectionAssembly*
6880 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6883 MonoReflectionAssembly *result;
6884 result = mono_assembly_get_object_checked (domain, assembly, &error);
6885 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6889 * mono_assembly_get_object_checked:
6890 * @domain: an app domain
6891 * @assembly: an assembly
6893 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6895 MonoReflectionAssembly*
6896 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6898 MonoReflectionAssembly *res;
6900 mono_error_init (error);
6902 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6903 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6906 res->assembly = assembly;
6908 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6913 MonoReflectionModule*
6914 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6917 MonoReflectionModule *result;
6918 result = mono_module_get_object_checked (domain, image, &error);
6919 mono_error_raise_exception (&error);
6923 MonoReflectionModule*
6924 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6926 MonoReflectionModule *res;
6929 mono_error_init (error);
6930 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6931 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6936 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6939 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6941 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6942 basename = g_path_get_basename (image->name);
6943 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6944 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6948 if (image->assembly->image == image) {
6949 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6953 if (image->assembly->image->modules) {
6954 for (i = 0; i < image->assembly->image->module_count; i++) {
6955 if (image->assembly->image->modules [i] == image)
6956 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6958 g_assert (res->token);
6962 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6965 MonoReflectionModule*
6966 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6969 MonoReflectionModule *result;
6970 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6971 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6975 MonoReflectionModule*
6976 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6978 MonoReflectionModule *res;
6979 MonoTableInfo *table;
6980 guint32 cols [MONO_FILE_SIZE];
6982 guint32 i, name_idx;
6985 mono_error_init (error);
6987 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6991 table = &image->tables [MONO_TABLE_FILE];
6992 g_assert (table_index < table->rows);
6993 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6996 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6999 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7000 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7002 /* Check whenever the row has a corresponding row in the moduleref table */
7003 table = &image->tables [MONO_TABLE_MODULEREF];
7004 for (i = 0; i < table->rows; ++i) {
7005 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7006 val = mono_metadata_string_heap (image, name_idx);
7007 if (strcmp (val, name) == 0)
7008 res->image = image->modules [i];
7011 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7012 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7013 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7014 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7015 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7021 verify_safe_for_managed_space (MonoType *type)
7023 switch (type->type) {
7025 case MONO_TYPE_ARRAY:
7026 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7028 return verify_safe_for_managed_space (type->data.type);
7029 case MONO_TYPE_SZARRAY:
7030 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7031 case MONO_TYPE_GENERICINST: {
7032 MonoGenericInst *inst = type->data.generic_class->inst;
7036 for (i = 0; i < inst->type_argc; ++i)
7037 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7043 case MONO_TYPE_MVAR:
7051 mono_type_normalize (MonoType *type)
7054 MonoGenericClass *gclass;
7055 MonoGenericInst *ginst;
7057 MonoGenericContainer *gcontainer;
7058 MonoType **argv = NULL;
7059 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7061 if (type->type != MONO_TYPE_GENERICINST)
7064 gclass = type->data.generic_class;
7065 ginst = gclass->context.class_inst;
7066 if (!ginst->is_open)
7069 gtd = gclass->container_class;
7070 gcontainer = gtd->generic_container;
7071 argv = g_newa (MonoType*, ginst->type_argc);
7073 for (i = 0; i < ginst->type_argc; ++i) {
7074 MonoType *t = ginst->type_argv [i], *norm;
7075 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7076 is_denorm_gtd = FALSE;
7077 norm = mono_type_normalize (t);
7080 requires_rebind = TRUE;
7084 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7086 if (requires_rebind) {
7087 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7088 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7094 * mono_type_get_object:
7095 * @domain: an app domain
7098 * Return an System.MonoType object representing the type @type.
7101 mono_type_get_object (MonoDomain *domain, MonoType *type)
7104 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7105 mono_error_raise_exception (&error);
7111 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7113 MonoType *norm_type;
7114 MonoReflectionType *res;
7117 mono_error_init (error);
7119 klass = mono_class_from_mono_type (type);
7121 /*we must avoid using @type as it might have come
7122 * from a mono_metadata_type_dup and the caller
7123 * expects that is can be freed.
7124 * Using the right type from
7126 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7128 /* void is very common */
7129 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7130 return (MonoReflectionType*)domain->typeof_void;
7133 * If the vtable of the given class was already created, we can use
7134 * the MonoType from there and avoid all locking and hash table lookups.
7136 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7137 * that the resulting object is different.
7139 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7140 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7141 if (vtable && vtable->type)
7142 return (MonoReflectionType *)vtable->type;
7145 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7146 mono_domain_lock (domain);
7147 if (!domain->type_hash)
7148 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7149 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7150 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7151 mono_domain_unlock (domain);
7152 mono_loader_unlock ();
7156 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7157 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7158 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7159 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7160 * artifact of how generics are encoded and should be transparent to managed code so we
7161 * need to weed out this diference when retrieving managed System.Type objects.
7163 norm_type = mono_type_normalize (type);
7164 if (norm_type != type) {
7165 res = mono_type_get_object_checked (domain, norm_type, error);
7166 if (!mono_error_ok (error))
7168 mono_g_hash_table_insert (domain->type_hash, type, res);
7169 mono_domain_unlock (domain);
7170 mono_loader_unlock ();
7174 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7175 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7178 if (!verify_safe_for_managed_space (type)) {
7179 mono_domain_unlock (domain);
7180 mono_loader_unlock ();
7181 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7185 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7186 gboolean is_type_done = TRUE;
7187 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7188 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7189 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7191 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7192 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7194 if (gparam->owner && gparam->owner->is_method) {
7195 MonoMethod *method = gparam->owner->owner.method;
7196 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7197 is_type_done = FALSE;
7198 } else if (gparam->owner && !gparam->owner->is_method) {
7199 MonoClass *klass = gparam->owner->owner.klass;
7200 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7201 is_type_done = FALSE;
7205 /* g_assert_not_reached (); */
7206 /* should this be considered an error condition? */
7207 if (is_type_done && !type->byref) {
7208 mono_domain_unlock (domain);
7209 mono_loader_unlock ();
7210 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7213 /* This is stored in vtables/JITted code so it has to be pinned */
7214 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7215 if (!mono_error_ok (error))
7219 mono_g_hash_table_insert (domain->type_hash, type, res);
7221 if (type->type == MONO_TYPE_VOID)
7222 domain->typeof_void = (MonoObject*)res;
7224 mono_domain_unlock (domain);
7225 mono_loader_unlock ();
7230 * mono_method_get_object:
7231 * @domain: an app domain
7233 * @refclass: the reflected type (can be NULL)
7235 * Return an System.Reflection.MonoMethod object representing the method @method.
7237 MonoReflectionMethod*
7238 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7241 MonoReflectionMethod *ret = NULL;
7242 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7243 mono_error_raise_exception (&error);
7248 * mono_method_get_object_checked:
7249 * @domain: an app domain
7251 * @refclass: the reflected type (can be NULL)
7252 * @error: set on error.
7254 * Return an System.Reflection.MonoMethod object representing the method @method.
7255 * Returns NULL and sets @error on error.
7257 MonoReflectionMethod*
7258 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7261 * We use the same C representation for methods and constructors, but the type
7262 * name in C# is different.
7264 MonoReflectionType *rt;
7266 MonoReflectionMethod *ret;
7268 mono_error_init (error);
7270 if (method->is_inflated) {
7271 MonoReflectionGenericMethod *gret;
7274 refclass = method->klass;
7275 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7276 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7277 klass = mono_class_get_mono_generic_cmethod_class ();
7279 klass = mono_class_get_mono_generic_method_class ();
7281 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7282 if (!mono_error_ok (error))
7284 gret->method.method = method;
7286 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7288 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7289 if (!mono_error_ok (error))
7292 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7294 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7298 refclass = method->klass;
7300 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7301 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7302 klass = mono_class_get_mono_cmethod_class ();
7305 klass = mono_class_get_mono_method_class ();
7307 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7308 if (!mono_error_ok (error))
7310 ret->method = method;
7312 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7313 if (!mono_error_ok (error))
7316 MONO_OBJECT_SETREF (ret, reftype, rt);
7318 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7321 g_assert (!mono_error_ok (error));
7326 * mono_method_clear_object:
7328 * Clear the cached reflection objects for the dynamic method METHOD.
7331 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7334 g_assert (method_is_dynamic (method));
7336 klass = method->klass;
7338 clear_cached_object (domain, method, klass);
7339 klass = klass->parent;
7341 /* Added by mono_param_get_objects () */
7342 clear_cached_object (domain, &(method->signature), NULL);
7343 klass = method->klass;
7345 clear_cached_object (domain, &(method->signature), klass);
7346 klass = klass->parent;
7351 * mono_field_get_object:
7352 * @domain: an app domain
7356 * Return an System.Reflection.MonoField object representing the field @field
7359 MonoReflectionField*
7360 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7363 MonoReflectionField *result;
7364 result = mono_field_get_object_checked (domain, klass, field, &error);
7365 mono_error_raise_exception (&error);
7370 * mono_field_get_object_checked:
7371 * @domain: an app domain
7374 * @error: set on error
7376 * Return an System.Reflection.MonoField object representing the field @field
7377 * in class @klass. On error, returns NULL and sets @error.
7379 MonoReflectionField*
7380 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7382 MonoReflectionType *rt;
7383 MonoReflectionField *res;
7385 mono_error_init (error);
7387 CHECK_OBJECT (MonoReflectionField *, field, klass);
7388 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7393 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7395 if (is_field_on_inst (field)) {
7396 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7398 rt = mono_type_get_object_checked (domain, field->type, error);
7399 if (!mono_error_ok (error))
7402 MONO_OBJECT_SETREF (res, type, rt);
7405 rt = mono_type_get_object_checked (domain, field->type, error);
7406 if (!mono_error_ok (error))
7409 MONO_OBJECT_SETREF (res, type, rt);
7411 res->attrs = mono_field_get_flags (field);
7413 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7417 * mono_property_get_object:
7418 * @domain: an app domain
7420 * @property: a property
7422 * Return an System.Reflection.MonoProperty object representing the property @property
7425 MonoReflectionProperty*
7426 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7429 MonoReflectionProperty *result;
7430 result = mono_property_get_object_checked (domain, klass, property, &error);
7431 mono_error_raise_exception (&error);
7436 * mono_property_get_object:
7437 * @domain: an app domain
7439 * @property: a property
7440 * @error: set on error
7442 * Return an System.Reflection.MonoProperty object representing the property @property
7443 * in class @klass. On error returns NULL and sets @error.
7445 MonoReflectionProperty*
7446 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7448 MonoReflectionProperty *res;
7450 mono_error_init (error);
7452 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7453 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7457 res->property = property;
7458 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7462 * mono_event_get_object:
7463 * @domain: an app domain
7467 * Return an System.Reflection.MonoEvent object representing the event @event
7470 MonoReflectionEvent*
7471 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7474 MonoReflectionEvent *result;
7475 result = mono_event_get_object_checked (domain, klass, event, &error);
7476 mono_error_raise_exception (&error);
7481 * mono_event_get_object_checked:
7482 * @domain: an app domain
7485 * @error: set on error
7487 * Return an System.Reflection.MonoEvent object representing the event @event
7488 * in class @klass. On failure sets @error and returns NULL
7490 MonoReflectionEvent*
7491 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7493 MonoReflectionEvent *res;
7494 MonoReflectionMonoEvent *mono_event;
7496 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7497 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7500 mono_event->klass = klass;
7501 mono_event->event = event;
7502 res = (MonoReflectionEvent*)mono_event;
7503 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7507 * mono_get_reflection_missing_object:
7508 * @domain: Domain where the object lives
7510 * Returns the System.Reflection.Missing.Value singleton object
7511 * (of type System.Reflection.Missing).
7513 * Used as the value for ParameterInfo.DefaultValue when Optional
7517 mono_get_reflection_missing_object (MonoDomain *domain)
7520 static MonoClassField *missing_value_field = NULL;
7522 if (!missing_value_field) {
7523 MonoClass *missing_klass;
7524 missing_klass = mono_class_get_missing_class ();
7525 mono_class_init (missing_klass);
7526 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7527 g_assert (missing_value_field);
7529 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7535 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7538 *dbnull = mono_get_dbnull_object (domain);
7543 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7545 if (!*reflection_missing)
7546 *reflection_missing = mono_get_reflection_missing_object (domain);
7547 return *reflection_missing;
7551 * mono_param_get_objects:
7552 * @domain: an app domain
7555 * Return an System.Reflection.ParameterInfo array object representing the parameters
7556 * in the method @method.
7559 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7561 static MonoClass *System_Reflection_ParameterInfo;
7562 static MonoClass *System_Reflection_ParameterInfo_array;
7564 MonoArray *res = NULL;
7565 MonoReflectionMethod *member = NULL;
7566 MonoReflectionParameter *param = NULL;
7567 char **names = NULL, **blobs = NULL;
7568 guint32 *types = NULL;
7569 MonoType *type = NULL;
7570 MonoObject *dbnull = NULL;
7571 MonoObject *missing = NULL;
7572 MonoMarshalSpec **mspecs = NULL;
7573 MonoMethodSignature *sig = NULL;
7574 MonoVTable *pinfo_vtable;
7575 MonoReflectionType *rt;
7578 mono_error_init (&error);
7580 if (!System_Reflection_ParameterInfo_array) {
7583 klass = mono_class_get_mono_parameter_info_class ();
7585 mono_memory_barrier ();
7586 System_Reflection_ParameterInfo = klass;
7589 klass = mono_array_class_get (klass, 1);
7590 mono_memory_barrier ();
7591 System_Reflection_ParameterInfo_array = klass;
7594 sig = mono_method_signature_checked (method, &error);
7595 if (!mono_error_ok (&error))
7598 if (!sig->param_count) {
7599 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7606 /* Note: the cache is based on the address of the signature into the method
7607 * since we already cache MethodInfos with the method as keys.
7609 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7611 member = mono_method_get_object_checked (domain, method, refclass, &error);
7614 names = g_new (char *, sig->param_count);
7615 mono_method_get_param_names (method, (const char **) names);
7617 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7618 mono_method_get_marshal_info (method, mspecs);
7620 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7624 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7625 for (i = 0; i < sig->param_count; ++i) {
7626 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7630 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7634 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7636 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7638 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7640 param->PositionImpl = i;
7641 param->AttrsImpl = sig->params [i]->attrs;
7643 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7644 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7645 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7647 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7651 blobs = g_new0 (char *, sig->param_count);
7652 types = g_new0 (guint32, sig->param_count);
7653 get_default_param_value_blobs (method, blobs, types);
7656 /* Build MonoType for the type from the Constant Table */
7658 type = g_new0 (MonoType, 1);
7659 type->type = (MonoTypeEnum)types [i];
7660 type->data.klass = NULL;
7661 if (types [i] == MONO_TYPE_CLASS)
7662 type->data.klass = mono_defaults.object_class;
7663 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7664 /* For enums, types [i] contains the base type */
7666 type->type = MONO_TYPE_VALUETYPE;
7667 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7669 type->data.klass = mono_class_from_mono_type (type);
7671 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7673 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7674 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7675 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7676 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7678 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7683 if (mspecs [i + 1]) {
7684 MonoReflectionMarshalAsAttribute* mobj;
7685 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7688 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7691 mono_array_setref (res, i, param);
7701 for (i = sig->param_count; i >= 0; i--) {
7703 mono_metadata_free_marshal_spec (mspecs [i]);
7708 mono_error_raise_exception (&error); /* FIXME don't raise here */
7710 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7714 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7716 return mono_param_get_objects_internal (domain, method, NULL);
7720 * mono_method_body_get_object:
7721 * @domain: an app domain
7724 * Return an System.Reflection.MethodBody object representing the method @method.
7726 MonoReflectionMethodBody*
7727 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7730 MonoReflectionMethodBody *ret;
7731 MonoMethodHeader *header;
7733 MonoReflectionType *rt;
7734 guint32 method_rva, local_var_sig_token;
7736 unsigned char format, flags;
7739 /* for compatibility with .net */
7740 if (method_is_dynamic (method))
7741 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7743 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7745 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7746 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7747 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7748 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7749 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7752 image = method->klass->image;
7753 header = mono_method_get_header_checked (method, &error);
7754 mono_error_raise_exception (&error); /* FIXME don't raise here */
7756 if (!image_is_dynamic (image)) {
7757 /* Obtain local vars signature token */
7758 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7759 ptr = mono_image_rva_map (image, method_rva);
7760 flags = *(const unsigned char *) ptr;
7761 format = flags & METHOD_HEADER_FORMAT_MASK;
7763 case METHOD_HEADER_TINY_FORMAT:
7764 local_var_sig_token = 0;
7766 case METHOD_HEADER_FAT_FORMAT:
7770 local_var_sig_token = read32 (ptr);
7773 g_assert_not_reached ();
7776 local_var_sig_token = 0; //FIXME
7778 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7779 mono_error_raise_exception (&error); /* FIXME don't raise here */
7781 ret->init_locals = header->init_locals;
7782 ret->max_stack = header->max_stack;
7783 ret->local_var_sig_token = local_var_sig_token;
7784 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7785 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7788 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7789 for (i = 0; i < header->num_locals; ++i) {
7790 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7791 mono_error_raise_exception (&error); /* FIXME don't raise here */
7793 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7794 mono_error_raise_exception (&error); /* FIXME don't raise here */
7796 MONO_OBJECT_SETREF (info, local_type, rt);
7798 info->is_pinned = header->locals [i]->pinned;
7799 info->local_index = i;
7800 mono_array_setref (ret->locals, i, info);
7804 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7805 for (i = 0; i < header->num_clauses; ++i) {
7806 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7807 mono_error_raise_exception (&error); /* FIXME don't raise here */
7808 MonoExceptionClause *clause = &header->clauses [i];
7810 info->flags = clause->flags;
7811 info->try_offset = clause->try_offset;
7812 info->try_length = clause->try_len;
7813 info->handler_offset = clause->handler_offset;
7814 info->handler_length = clause->handler_len;
7815 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7816 info->filter_offset = clause->data.filter_offset;
7817 else if (clause->data.catch_class) {
7818 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7819 mono_error_raise_exception (&error); /* FIXME don't raise here */
7821 MONO_OBJECT_SETREF (info, catch_type, rt);
7824 mono_array_setref (ret->clauses, i, info);
7827 mono_metadata_free_mh (header);
7828 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7833 * mono_get_dbnull_object:
7834 * @domain: Domain where the object lives
7836 * Returns the System.DBNull.Value singleton object
7838 * Used as the value for ParameterInfo.DefaultValue
7841 mono_get_dbnull_object (MonoDomain *domain)
7844 static MonoClassField *dbnull_value_field = NULL;
7846 if (!dbnull_value_field) {
7847 MonoClass *dbnull_klass;
7848 dbnull_klass = mono_class_get_dbnull_class ();
7849 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7850 g_assert (dbnull_value_field);
7852 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7858 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7860 guint32 param_index, i, lastp, crow = 0;
7861 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7864 MonoClass *klass = method->klass;
7865 MonoImage *image = klass->image;
7866 MonoMethodSignature *methodsig = mono_method_signature (method);
7868 MonoTableInfo *constt;
7869 MonoTableInfo *methodt;
7870 MonoTableInfo *paramt;
7872 if (!methodsig->param_count)
7875 mono_class_init (klass);
7877 if (image_is_dynamic (klass->image)) {
7878 MonoReflectionMethodAux *aux;
7879 if (method->is_inflated)
7880 method = ((MonoMethodInflated*)method)->declaring;
7881 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7882 if (aux && aux->param_defaults) {
7883 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7884 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7889 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7890 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7891 constt = &image->tables [MONO_TABLE_CONSTANT];
7893 idx = mono_method_get_index (method) - 1;
7894 g_assert (idx != -1);
7896 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7897 if (idx + 1 < methodt->rows)
7898 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7900 lastp = paramt->rows + 1;
7902 for (i = param_index; i < lastp; ++i) {
7905 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7906 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7908 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7911 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7916 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7917 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7918 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7925 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7931 MonoType *basetype = type;
7936 klass = mono_class_from_mono_type (type);
7937 if (klass->valuetype) {
7938 object = mono_object_new_checked (domain, klass, &error);
7939 mono_error_raise_exception (&error); /* FIXME don't raise here */
7940 retval = ((gchar *) object + sizeof (MonoObject));
7941 if (klass->enumtype)
7942 basetype = mono_class_enum_basetype (klass);
7947 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7954 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7957 gboolean quoted = FALSE;
7959 memset (assembly, 0, sizeof (MonoAssemblyName));
7960 assembly->culture = "";
7961 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7968 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7979 /* Remove trailing whitespace */
7981 while (*s && g_ascii_isspace (*s))
7984 while (g_ascii_isspace (*p))
7987 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7989 assembly->major = strtoul (p, &s, 10);
7990 if (s == p || *s != '.')
7993 assembly->minor = strtoul (p, &s, 10);
7994 if (s == p || *s != '.')
7997 assembly->build = strtoul (p, &s, 10);
7998 if (s == p || *s != '.')
8001 assembly->revision = strtoul (p, &s, 10);
8005 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8007 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8008 assembly->culture = "";
8011 assembly->culture = p;
8012 while (*p && *p != ',') {
8016 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8018 if (strncmp (p, "null", 4) == 0) {
8023 while (*p && *p != ',') {
8026 len = (p - start + 1);
8027 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8028 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8029 g_strlcpy ((char*)assembly->public_key_token, start, len);
8032 while (*p && *p != ',')
8036 while (g_ascii_isspace (*p) || *p == ',') {
8050 * mono_reflection_parse_type:
8053 * Parse a type name as accepted by the GetType () method and output the info
8054 * extracted in the info structure.
8055 * the name param will be mangled, so, make a copy before passing it to this function.
8056 * The fields in info will be valid until the memory pointed to by name is valid.
8058 * See also mono_type_get_name () below.
8060 * Returns: 0 on parse error.
8063 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8064 MonoTypeNameParse *info)
8066 char *start, *p, *w, *last_point, *startn;
8067 int in_modifiers = 0;
8068 int isbyref = 0, rank = 0, isptr = 0;
8070 start = p = w = name;
8072 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8073 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8074 info->name = info->name_space = NULL;
8075 info->nested = NULL;
8076 info->modifiers = NULL;
8077 info->type_arguments = NULL;
8079 /* last_point separates the namespace from the name */
8082 while (*p == ' ') p++, start++, w++, name++;
8087 *p = 0; /* NULL terminate the name */
8089 info->nested = g_list_append (info->nested, startn);
8090 /* we have parsed the nesting namespace + name */
8094 info->name_space = start;
8096 info->name = last_point + 1;
8098 info->name_space = (char *)"";
8126 info->name_space = start;
8128 info->name = last_point + 1;
8130 info->name_space = (char *)"";
8137 if (isbyref) /* only one level allowed by the spec */
8141 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8145 if (isbyref) /* pointer to ref not okay */
8147 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8152 if (isbyref) /* array of ref and generic ref are not okay */
8154 //Decide if it's an array of a generic argument list
8159 if (*p == ',' || *p == '*' || *p == ']') { //array
8167 else if (*p == '*') /* '*' means unknown lower bound */
8168 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8175 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8177 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8180 info->type_arguments = g_ptr_array_new ();
8182 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8183 gboolean fqname = FALSE;
8185 g_ptr_array_add (info->type_arguments, subinfo);
8187 while (*p == ' ') p++;
8193 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8196 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8197 if (fqname && (*p != ']')) {
8205 while (*p && (*p != ']'))
8213 if (g_ascii_isspace (*aname)) {
8220 !assembly_name_to_aname (&subinfo->assembly, aname))
8222 } else if (fqname && (*p == ']')) {
8244 if (g_ascii_isspace (*p)) {
8251 return 0; /* missing assembly name */
8252 if (!assembly_name_to_aname (&info->assembly, p))
8258 if (info->assembly.name)
8261 // *w = 0; /* terminate class name */
8263 if (!info->name || !*info->name)
8267 /* add other consistency checks */
8273 * mono_identifier_unescape_type_name_chars:
8274 * @identifier: the display name of a mono type
8277 * The name in internal form, that is without escaping backslashes.
8279 * The string is modified in place!
8282 mono_identifier_unescape_type_name_chars(char* identifier)
8287 for (w = r = identifier; *r != 0; r++)
8305 mono_identifier_unescape_info (MonoTypeNameParse* info);
8308 unescape_each_type_argument(void* data, void* user_data)
8310 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8311 mono_identifier_unescape_info (info);
8315 unescape_each_nested_name (void* data, void* user_data)
8317 char* nested_name = (char*) data;
8318 mono_identifier_unescape_type_name_chars(nested_name);
8322 * mono_identifier_unescape_info:
8324 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8328 * Destructively updates the info by unescaping the identifiers that
8329 * comprise the type namespace, name, nested types (if any) and
8330 * generic type arguments (if any).
8332 * The resulting info has the names in internal form.
8336 mono_identifier_unescape_info (MonoTypeNameParse *info)
8340 mono_identifier_unescape_type_name_chars(info->name_space);
8341 mono_identifier_unescape_type_name_chars(info->name);
8342 // but don't escape info->assembly
8343 if (info->type_arguments)
8344 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8346 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8350 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8352 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8354 mono_identifier_unescape_info (info);
8360 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8362 gboolean type_resolve = FALSE;
8364 MonoImage *rootimage = image;
8366 if (info->assembly.name) {
8367 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8368 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8370 * This could happen in the AOT compiler case when the search hook is not
8373 assembly = image->assembly;
8375 /* then we must load the assembly ourselve - see #60439 */
8376 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8380 image = assembly->image;
8381 } else if (!image) {
8382 image = mono_defaults.corlib;
8385 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8386 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8387 image = mono_defaults.corlib;
8388 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8395 * mono_reflection_get_type_internal:
8397 * Returns: may return NULL on success, sets error on failure.
8400 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8405 gboolean bounded = FALSE;
8407 mono_error_init (error);
8409 image = mono_defaults.corlib;
8412 rootimage = mono_defaults.corlib;
8415 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8417 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8422 for (mod = info->nested; mod; mod = mod->next) {
8423 gpointer iter = NULL;
8427 mono_class_init (parent);
8429 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8431 char *nested_name, *nested_nspace;
8432 gboolean match = TRUE;
8434 lastp = strrchr ((const char *)mod->data, '.');
8436 /* Nested classes can have namespaces */
8439 nested_name = g_strdup (lastp + 1);
8440 nspace_len = lastp - (char*)mod->data;
8441 nested_nspace = (char *)g_malloc (nspace_len + 1);
8442 memcpy (nested_nspace, mod->data, nspace_len);
8443 nested_nspace [nspace_len] = '\0';
8446 nested_name = (char *)mod->data;
8447 nested_nspace = NULL;
8450 if (nested_nspace) {
8452 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8455 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8461 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8464 if (strcmp (klass->name, nested_name) != 0)
8469 g_free (nested_name);
8470 g_free (nested_nspace);
8482 if (info->type_arguments) {
8483 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8484 MonoReflectionType *the_type;
8488 for (i = 0; i < info->type_arguments->len; i++) {
8489 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8491 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8492 if (!type_args [i]) {
8498 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8502 instance = mono_reflection_bind_generic_parameters (
8503 the_type, info->type_arguments->len, type_args);
8509 klass = mono_class_from_mono_type (instance);
8512 for (mod = info->modifiers; mod; mod = mod->next) {
8513 modval = GPOINTER_TO_UINT (mod->data);
8514 if (!modval) { /* byref: must be last modifier */
8515 return &klass->this_arg;
8516 } else if (modval == -1) {
8517 klass = mono_ptr_class_get (&klass->byval_arg);
8518 } else if (modval == -2) {
8520 } else { /* array rank */
8521 klass = mono_bounded_array_class_get (klass, modval, bounded);
8525 return &klass->byval_arg;
8529 * mono_reflection_get_type:
8530 * @image: a metadata context
8531 * @info: type description structure
8532 * @ignorecase: flag for case-insensitive string compares
8533 * @type_resolve: whenever type resolve was already tried
8535 * Build a MonoType from the type description in @info.
8540 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8541 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8545 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8547 MonoReflectionAssemblyBuilder *abuilder;
8551 mono_error_init (error);
8552 g_assert (assembly_is_dynamic (assembly));
8553 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8557 /* Enumerate all modules */
8560 if (abuilder->modules) {
8561 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8562 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8563 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8566 if (!mono_error_ok (error))
8571 if (!type && abuilder->loaded_modules) {
8572 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8573 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8574 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8577 if (!mono_error_ok (error))
8586 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8590 MonoReflectionAssembly *assembly;
8594 if (image && image_is_dynamic (image))
8595 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8597 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8599 if (!mono_error_ok (&error))
8600 mono_error_raise_exception (&error); /* FIXME don't raise here */
8604 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8611 *type_resolve = TRUE;
8614 /* Reconstruct the type name */
8615 fullName = g_string_new ("");
8616 if (info->name_space && (info->name_space [0] != '\0'))
8617 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8619 g_string_printf (fullName, "%s", info->name);
8620 for (mod = info->nested; mod; mod = mod->next)
8621 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8623 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8624 mono_error_raise_exception (&error); /* FIXME don't raise here */
8627 if (assembly_is_dynamic (assembly->assembly))
8628 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8629 info, ignorecase, &error);
8631 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8632 info, ignorecase, &error);
8634 g_string_free (fullName, TRUE);
8635 if (!mono_error_ok (&error))
8636 mono_error_raise_exception (&error); /* FIXME don't raise here */
8641 mono_reflection_free_type_info (MonoTypeNameParse *info)
8643 g_list_free (info->modifiers);
8644 g_list_free (info->nested);
8646 if (info->type_arguments) {
8649 for (i = 0; i < info->type_arguments->len; i++) {
8650 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8652 mono_reflection_free_type_info (subinfo);
8653 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8657 g_ptr_array_free (info->type_arguments, TRUE);
8662 * mono_reflection_type_from_name:
8664 * @image: a metadata context (can be NULL).
8666 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8667 * it defaults to get the type from @image or, if @image is NULL or loading
8668 * from it fails, uses corlib.
8672 mono_reflection_type_from_name (char *name, MonoImage *image)
8674 MonoType *type = NULL;
8675 MonoTypeNameParse info;
8678 /* Make a copy since parse_type modifies its argument */
8679 tmp = g_strdup (name);
8681 /*g_print ("requested type %s\n", str);*/
8682 if (mono_reflection_parse_type (tmp, &info)) {
8683 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8687 mono_reflection_free_type_info (&info);
8692 * mono_reflection_get_token:
8694 * Return the metadata token of OBJ which should be an object
8695 * representing a metadata element.
8698 mono_reflection_get_token (MonoObject *obj)
8704 klass = obj->vtable->klass;
8706 if (strcmp (klass->name, "MethodBuilder") == 0) {
8707 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8709 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8710 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8711 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8713 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8714 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8715 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8717 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8718 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8719 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8720 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8721 } else if (strcmp (klass->name, "MonoType") == 0) {
8722 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8723 mono_error_raise_exception (&error); /* FIXME don't raise here */
8724 MonoClass *mc = mono_class_from_mono_type (type);
8725 if (!mono_class_init (mc))
8726 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8728 token = mc->type_token;
8729 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8730 strcmp (klass->name, "MonoMethod") == 0 ||
8731 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8732 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8733 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8734 if (m->method->is_inflated) {
8735 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8736 return inflated->declaring->token;
8738 token = m->method->token;
8740 } else if (strcmp (klass->name, "MonoField") == 0) {
8741 MonoReflectionField *f = (MonoReflectionField*)obj;
8743 if (is_field_on_inst (f->field)) {
8744 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8746 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8747 int field_index = f->field - dgclass->fields;
8750 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8751 obj = dgclass->field_objects [field_index];
8752 return mono_reflection_get_token (obj);
8755 token = mono_class_get_field_token (f->field);
8756 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8757 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8759 token = mono_class_get_property_token (p->property);
8760 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8761 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8763 token = mono_class_get_event_token (p->event);
8764 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8765 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8766 MonoClass *member_class = mono_object_class (p->MemberImpl);
8767 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8769 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8770 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8771 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8774 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8775 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8777 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8778 MonoException *ex = mono_get_exception_not_implemented (msg);
8780 mono_raise_exception (ex);
8787 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8791 int slen = mono_metadata_decode_value (p, &p);
8793 mono_error_init (error);
8795 n = (char *)g_memdup (p, slen + 1);
8797 t = mono_reflection_type_from_name (n, image);
8799 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8800 /* We don't free n, it's consumed by mono_error */
8801 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8807 return mono_class_from_mono_type (t);
8811 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8813 int slen, type = t->type;
8814 MonoClass *tklass = t->data.klass;
8816 mono_error_init (error);
8822 case MONO_TYPE_BOOLEAN: {
8823 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8828 case MONO_TYPE_CHAR:
8830 case MONO_TYPE_I2: {
8831 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8836 #if SIZEOF_VOID_P == 4
8842 case MONO_TYPE_I4: {
8843 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8848 #if SIZEOF_VOID_P == 8
8849 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8853 case MONO_TYPE_I8: {
8854 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8859 case MONO_TYPE_R8: {
8860 double *val = (double *)g_malloc (sizeof (double));
8865 case MONO_TYPE_VALUETYPE:
8866 if (t->data.klass->enumtype) {
8867 type = mono_class_enum_basetype (t->data.klass)->type;
8870 MonoClass *k = t->data.klass;
8872 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8873 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8879 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8882 case MONO_TYPE_STRING:
8883 if (*p == (char)0xFF) {
8887 slen = mono_metadata_decode_value (p, &p);
8889 return mono_string_new_len (mono_domain_get (), p, slen);
8890 case MONO_TYPE_CLASS: {
8891 MonoReflectionType *rt;
8894 if (*p == (char)0xFF) {
8899 slen = mono_metadata_decode_value (p, &p);
8900 n = (char *)g_memdup (p, slen + 1);
8902 t = mono_reflection_type_from_name (n, image);
8904 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8905 /* We don't free n, it's consumed by mono_error */
8906 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8912 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8913 if (!mono_error_ok (error))
8918 case MONO_TYPE_OBJECT: {
8921 MonoClass *subc = NULL;
8926 } else if (subt == 0x0E) {
8927 type = MONO_TYPE_STRING;
8929 } else if (subt == 0x1D) {
8930 MonoType simple_type = {{0}};
8934 type = MONO_TYPE_SZARRAY;
8935 if (etype == 0x50) {
8936 tklass = mono_defaults.systemtype_class;
8937 } else if (etype == 0x55) {
8938 tklass = load_cattr_enum_type (image, p, &p, error);
8939 if (!mono_error_ok (error))
8943 /* See Partition II, Appendix B3 */
8944 etype = MONO_TYPE_OBJECT;
8945 simple_type.type = (MonoTypeEnum)etype;
8946 tklass = mono_class_from_mono_type (&simple_type);
8949 } else if (subt == 0x55) {
8952 slen = mono_metadata_decode_value (p, &p);
8953 n = (char *)g_memdup (p, slen + 1);
8955 t = mono_reflection_type_from_name (n, image);
8957 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8958 /* We don't free n, it's consumed by mono_error */
8959 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8964 subc = mono_class_from_mono_type (t);
8965 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8966 MonoType simple_type = {{0}};
8967 simple_type.type = (MonoTypeEnum)subt;
8968 subc = mono_class_from_mono_type (&simple_type);
8970 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8972 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8974 if (mono_error_ok (error)) {
8975 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8976 g_assert (!subc->has_references);
8977 if (mono_error_ok (error))
8978 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8984 case MONO_TYPE_SZARRAY: {
8986 guint32 i, alen, basetype;
8989 if (alen == 0xffffffff) {
8993 arr = mono_array_new (mono_domain_get(), tklass, alen);
8994 basetype = tklass->byval_arg.type;
8995 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8996 basetype = mono_class_enum_basetype (tklass)->type;
9001 case MONO_TYPE_BOOLEAN:
9002 for (i = 0; i < alen; i++) {
9003 MonoBoolean val = *p++;
9004 mono_array_set (arr, MonoBoolean, i, val);
9007 case MONO_TYPE_CHAR:
9010 for (i = 0; i < alen; i++) {
9011 guint16 val = read16 (p);
9012 mono_array_set (arr, guint16, i, val);
9019 for (i = 0; i < alen; i++) {
9020 guint32 val = read32 (p);
9021 mono_array_set (arr, guint32, i, val);
9026 for (i = 0; i < alen; i++) {
9029 mono_array_set (arr, double, i, val);
9035 for (i = 0; i < alen; i++) {
9036 guint64 val = read64 (p);
9037 mono_array_set (arr, guint64, i, val);
9041 case MONO_TYPE_CLASS:
9042 case MONO_TYPE_OBJECT:
9043 case MONO_TYPE_STRING:
9044 case MONO_TYPE_SZARRAY:
9045 for (i = 0; i < alen; i++) {
9046 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9047 if (!mono_error_ok (error))
9049 mono_array_setref (arr, i, item);
9053 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9059 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9065 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9067 static MonoMethod *ctor;
9069 void *params [2], *unboxed;
9071 mono_error_init (error);
9074 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9076 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9077 return_val_if_nok (error, NULL);
9080 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9081 return_val_if_nok (error, NULL);
9082 unboxed = mono_object_unbox (retval);
9084 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9085 return_val_if_nok (error, NULL);
9091 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9093 static MonoMethod *ctor;
9095 void *unboxed, *params [2];
9097 mono_error_init (error);
9100 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9103 params [1] = typedarg;
9104 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9105 return_val_if_nok (error, NULL);
9107 unboxed = mono_object_unbox (retval);
9109 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9110 return_val_if_nok (error, NULL);
9116 type_is_reference (MonoType *type)
9118 switch (type->type) {
9119 case MONO_TYPE_BOOLEAN:
9120 case MONO_TYPE_CHAR:
9133 case MONO_TYPE_VALUETYPE:
9141 free_param_data (MonoMethodSignature *sig, void **params) {
9143 for (i = 0; i < sig->param_count; ++i) {
9144 if (!type_is_reference (sig->params [i]))
9145 g_free (params [i]);
9150 * Find the field index in the metadata FieldDef table.
9153 find_field_index (MonoClass *klass, MonoClassField *field) {
9156 for (i = 0; i < klass->field.count; ++i) {
9157 if (field == &klass->fields [i])
9158 return klass->field.first + 1 + i;
9164 * Find the property index in the metadata Property table.
9167 find_property_index (MonoClass *klass, MonoProperty *property) {
9170 for (i = 0; i < klass->ext->property.count; ++i) {
9171 if (property == &klass->ext->properties [i])
9172 return klass->ext->property.first + 1 + i;
9178 * Find the event index in the metadata Event table.
9181 find_event_index (MonoClass *klass, MonoEvent *event) {
9184 for (i = 0; i < klass->ext->event.count; ++i) {
9185 if (event == &klass->ext->events [i])
9186 return klass->ext->event.first + 1 + i;
9192 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9194 const char *p = (const char*)data;
9196 guint32 i, j, num_named;
9198 void *params_buf [32];
9199 void **params = NULL;
9200 MonoMethodSignature *sig;
9201 MonoObject *exc = NULL;
9203 mono_error_init (error);
9205 mono_class_init (method->klass);
9207 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9208 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9213 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9214 if (!mono_error_ok (error)) return NULL;
9216 mono_runtime_invoke_checked (method, attr, NULL, error);
9217 if (!mono_error_ok (error))
9223 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9226 /*g_print ("got attr %s\n", method->klass->name);*/
9228 sig = mono_method_signature (method);
9229 if (sig->param_count < 32) {
9230 params = params_buf;
9231 memset (params, 0, sizeof (void*) * sig->param_count);
9233 /* Allocate using GC so it gets GC tracking */
9234 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9239 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9240 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9241 if (!mono_error_ok (error))
9246 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9247 if (!mono_error_ok (error)) goto fail;
9249 mono_runtime_try_invoke (method, attr, params, &exc, error);
9250 if (!mono_error_ok (error))
9255 num_named = read16 (named);
9257 for (j = 0; j < num_named; j++) {
9259 char *name, named_type, data_type;
9260 named_type = *named++;
9261 data_type = *named++; /* type of data */
9262 if (data_type == MONO_TYPE_SZARRAY)
9263 data_type = *named++;
9264 if (data_type == MONO_TYPE_ENUM) {
9267 type_len = mono_metadata_decode_blob_size (named, &named);
9268 type_name = (char *)g_malloc (type_len + 1);
9269 memcpy (type_name, named, type_len);
9270 type_name [type_len] = 0;
9272 /* FIXME: lookup the type and check type consistency */
9275 name_len = mono_metadata_decode_blob_size (named, &named);
9276 name = (char *)g_malloc (name_len + 1);
9277 memcpy (name, named, name_len);
9278 name [name_len] = 0;
9280 if (named_type == 0x53) {
9281 MonoClassField *field;
9284 /* how this fail is a blackbox */
9285 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9287 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9292 val = load_cattr_value (image, field->type, named, &named, error);
9293 if (!mono_error_ok (error)) {
9295 if (!type_is_reference (field->type))
9300 mono_field_set_value (attr, field, val);
9301 if (!type_is_reference (field->type))
9303 } else if (named_type == 0x54) {
9306 MonoType *prop_type;
9308 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9311 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9317 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9322 /* can we have more that 1 arg in a custom attr named property? */
9323 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9324 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9326 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9327 if (!mono_error_ok (error)) {
9329 if (!type_is_reference (prop_type))
9330 g_free (pparams [0]);
9335 mono_property_set_value (prop, attr, pparams, NULL);
9336 if (!type_is_reference (prop_type))
9337 g_free (pparams [0]);
9342 free_param_data (method->signature, params);
9343 if (params != params_buf)
9344 mono_gc_free_fixed (params);
9349 free_param_data (method->signature, params);
9350 if (params != params_buf)
9351 mono_gc_free_fixed (params);
9353 mono_raise_exception ((MonoException*)exc);
9358 * mono_reflection_create_custom_attr_data_args:
9360 * Create an array of typed and named arguments from the cattr blob given by DATA.
9361 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9362 * NAMED_ARG_INFO will contain information about the named arguments.
9365 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)
9367 MonoArray *typedargs, *namedargs;
9368 MonoClass *attrklass;
9370 const char *p = (const char*)data;
9372 guint32 i, j, num_named;
9373 CattrNamedArg *arginfo = NULL;
9377 *named_arg_info = NULL;
9379 mono_error_init (error);
9381 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9382 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9386 mono_class_init (method->klass);
9388 domain = mono_domain_get ();
9390 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9393 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9397 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9401 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9402 if (!mono_error_ok (error)) {
9403 if (!type_is_reference (mono_method_signature (method)->params [i]))
9408 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9409 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9410 mono_array_setref (typedargs, i, obj);
9412 if (!type_is_reference (mono_method_signature (method)->params [i]))
9417 num_named = read16 (named);
9418 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9420 attrklass = method->klass;
9422 arginfo = g_new0 (CattrNamedArg, num_named);
9423 *named_arg_info = arginfo;
9425 for (j = 0; j < num_named; j++) {
9427 char *name, named_type, data_type;
9428 named_type = *named++;
9429 data_type = *named++; /* type of data */
9430 if (data_type == MONO_TYPE_SZARRAY)
9431 data_type = *named++;
9432 if (data_type == MONO_TYPE_ENUM) {
9435 type_len = mono_metadata_decode_blob_size (named, &named);
9436 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9439 type_name = (char *)g_malloc (type_len + 1);
9440 memcpy (type_name, named, type_len);
9441 type_name [type_len] = 0;
9443 /* FIXME: lookup the type and check type consistency */
9446 name_len = mono_metadata_decode_blob_size (named, &named);
9447 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9449 name = (char *)g_malloc (name_len + 1);
9450 memcpy (name, named, name_len);
9451 name [name_len] = 0;
9453 if (named_type == 0x53) {
9455 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9463 arginfo [j].type = field->type;
9464 arginfo [j].field = field;
9466 val = load_cattr_value (image, field->type, named, &named, error);
9467 if (!mono_error_ok (error)) {
9468 if (!type_is_reference (field->type))
9474 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9475 mono_array_setref (namedargs, j, obj);
9476 if (!type_is_reference (field->type))
9478 } else if (named_type == 0x54) {
9480 MonoType *prop_type;
9481 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9484 if (!prop || !prop->set) {
9489 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9490 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9492 arginfo [j].type = prop_type;
9493 arginfo [j].prop = prop;
9495 val = load_cattr_value (image, prop_type, named, &named, error);
9496 if (!mono_error_ok (error)) {
9497 if (!type_is_reference (prop_type))
9503 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9504 mono_array_setref (namedargs, j, obj);
9505 if (!type_is_reference (prop_type))
9511 *typed_args = typedargs;
9512 *named_args = namedargs;
9515 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9517 *named_arg_info = NULL;
9521 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9524 MonoArray *typedargs, *namedargs;
9527 CattrNamedArg *arginfo = NULL;
9531 mono_error_init (&error);
9539 image = assembly->assembly->image;
9540 method = ref_method->method;
9541 domain = mono_object_domain (ref_method);
9543 if (!mono_class_init (method->klass))
9544 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9546 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9547 if (!mono_error_ok (&error))
9550 if (mono_loader_get_last_error ()) {
9551 mono_error_set_from_loader_error (&error);
9555 if (!typedargs || !namedargs)
9558 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9559 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9560 MonoObject *typedarg;
9562 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9563 if (!is_ok (&error))
9565 mono_array_setref (typedargs, i, typedarg);
9568 for (i = 0; i < mono_array_length (namedargs); ++i) {
9569 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9570 MonoObject *typedarg, *namedarg, *minfo;
9572 if (arginfo [i].prop) {
9573 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9577 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9578 if (!mono_error_ok (&error))
9582 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9583 if (!is_ok (&error))
9585 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9586 if (!is_ok (&error))
9589 mono_array_setref (namedargs, i, namedarg);
9592 *ctor_args = typedargs;
9593 *named_args = namedargs;
9596 mono_error_raise_exception (&error);
9601 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9603 static MonoMethod *ctor;
9609 mono_error_init (error);
9611 g_assert (image->assembly);
9614 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9616 domain = mono_domain_get ();
9617 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9618 return_val_if_nok (error, NULL);
9619 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9620 return_val_if_nok (error, NULL);
9621 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9622 return_val_if_nok (error, NULL);
9623 params [2] = (gpointer)&cattr->data;
9624 params [3] = &cattr->data_size;
9626 mono_runtime_invoke_checked (ctor, attr, params, error);
9627 return_val_if_nok (error, NULL);
9632 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9638 mono_error_init (error);
9641 for (i = 0; i < cinfo->num_attrs; ++i) {
9642 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9646 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9648 for (i = 0; i < cinfo->num_attrs; ++i) {
9649 if (!cinfo->attrs [i].ctor) {
9650 /* The cattr type is not finished yet */
9651 /* We should include the type name but cinfo doesn't contain it */
9652 mono_error_set_type_load_name (error, NULL, NULL, "");
9655 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9656 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9657 if (!mono_error_ok (error))
9659 mono_array_setref (result, n, attr);
9667 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9670 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9671 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9677 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9683 mono_error_init (error);
9684 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9685 for (i = 0; i < cinfo->num_attrs; ++i) {
9686 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9687 return_val_if_nok (error, NULL);
9688 mono_array_setref (result, i, attr);
9694 * mono_custom_attrs_from_index:
9696 * Returns: NULL if no attributes are found or if a loading error occurs.
9699 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9702 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9703 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9707 * mono_custom_attrs_from_index_checked:
9709 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9712 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9714 guint32 mtoken, i, len;
9715 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9717 MonoCustomAttrInfo *ainfo;
9718 GList *tmp, *list = NULL;
9720 MonoCustomAttrEntry* attr;
9722 mono_error_init (error);
9724 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9726 i = mono_metadata_custom_attrs_from_index (image, idx);
9730 while (i < ca->rows) {
9731 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9733 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9736 len = g_list_length (list);
9739 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9740 ainfo->num_attrs = len;
9741 ainfo->image = image;
9742 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9743 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9744 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9745 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9746 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9747 mtoken |= MONO_TOKEN_METHOD_DEF;
9749 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9750 mtoken |= MONO_TOKEN_MEMBER_REF;
9753 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9756 attr = &ainfo->attrs [i - 1];
9757 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9759 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9765 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9766 /*FIXME raising an exception here doesn't make any sense*/
9767 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9772 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9773 attr->data_size = mono_metadata_decode_value (data, &data);
9774 attr->data = (guchar*)data;
9782 mono_custom_attrs_from_method (MonoMethod *method)
9785 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9786 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9791 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9795 mono_error_init (error);
9798 * An instantiated method has the same cattrs as the generic method definition.
9800 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9801 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9803 if (method->is_inflated)
9804 method = ((MonoMethodInflated *) method)->declaring;
9806 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9807 return lookup_custom_attr (method->klass->image, method);
9810 /* Synthetic methods */
9813 idx = mono_method_get_index (method);
9814 idx <<= MONO_CUSTOM_ATTR_BITS;
9815 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9816 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9820 mono_custom_attrs_from_class (MonoClass *klass)
9823 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9824 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9829 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9833 mono_error_init (error);
9835 if (klass->generic_class)
9836 klass = klass->generic_class->container_class;
9838 if (image_is_dynamic (klass->image))
9839 return lookup_custom_attr (klass->image, klass);
9841 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9842 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9843 idx <<= MONO_CUSTOM_ATTR_BITS;
9844 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9846 idx = mono_metadata_token_index (klass->type_token);
9847 idx <<= MONO_CUSTOM_ATTR_BITS;
9848 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9850 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9854 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9857 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9858 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9863 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9867 mono_error_init (error);
9869 if (image_is_dynamic (assembly->image))
9870 return lookup_custom_attr (assembly->image, assembly);
9871 idx = 1; /* there is only one assembly */
9872 idx <<= MONO_CUSTOM_ATTR_BITS;
9873 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9874 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9877 static MonoCustomAttrInfo*
9878 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9882 if (image_is_dynamic (image))
9883 return lookup_custom_attr (image, image);
9884 idx = 1; /* there is only one module */
9885 idx <<= MONO_CUSTOM_ATTR_BITS;
9886 idx |= MONO_CUSTOM_ATTR_MODULE;
9887 return mono_custom_attrs_from_index_checked (image, idx, error);
9891 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9894 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9895 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9900 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9904 if (image_is_dynamic (klass->image)) {
9905 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9906 return lookup_custom_attr (klass->image, property);
9908 idx = find_property_index (klass, property);
9909 idx <<= MONO_CUSTOM_ATTR_BITS;
9910 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9911 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9915 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9918 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9919 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9924 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9928 if (image_is_dynamic (klass->image)) {
9929 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9930 return lookup_custom_attr (klass->image, event);
9932 idx = find_event_index (klass, event);
9933 idx <<= MONO_CUSTOM_ATTR_BITS;
9934 idx |= MONO_CUSTOM_ATTR_EVENT;
9935 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9939 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9942 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9943 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9948 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9951 mono_error_init (error);
9953 if (image_is_dynamic (klass->image)) {
9954 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9955 return lookup_custom_attr (klass->image, field);
9957 idx = find_field_index (klass, field);
9958 idx <<= MONO_CUSTOM_ATTR_BITS;
9959 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9960 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9964 * mono_custom_attrs_from_param:
9965 * @method: handle to the method that we want to retrieve custom parameter information from
9966 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9968 * The result must be released with mono_custom_attrs_free().
9970 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9973 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9976 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9977 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9982 * mono_custom_attrs_from_param_checked:
9983 * @method: handle to the method that we want to retrieve custom parameter information from
9984 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9985 * @error: set on error
9987 * The result must be released with mono_custom_attrs_free().
9989 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9992 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9995 guint32 i, idx, method_index;
9996 guint32 param_list, param_last, param_pos, found;
9998 MonoReflectionMethodAux *aux;
10000 mono_error_init (error);
10003 * An instantiated method has the same cattrs as the generic method definition.
10005 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10006 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10008 if (method->is_inflated)
10009 method = ((MonoMethodInflated *) method)->declaring;
10011 if (image_is_dynamic (method->klass->image)) {
10012 MonoCustomAttrInfo *res, *ainfo;
10015 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10016 if (!aux || !aux->param_cattr)
10019 /* Need to copy since it will be freed later */
10020 ainfo = aux->param_cattr [param];
10023 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10024 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10025 memcpy (res, ainfo, size);
10029 image = method->klass->image;
10030 method_index = mono_method_get_index (method);
10033 ca = &image->tables [MONO_TABLE_METHOD];
10035 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10036 if (method_index == ca->rows) {
10037 ca = &image->tables [MONO_TABLE_PARAM];
10038 param_last = ca->rows + 1;
10040 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10041 ca = &image->tables [MONO_TABLE_PARAM];
10044 for (i = param_list; i < param_last; ++i) {
10045 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10046 if (param_pos == param) {
10054 idx <<= MONO_CUSTOM_ATTR_BITS;
10055 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10056 return mono_custom_attrs_from_index_checked (image, idx, error);
10060 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10064 for (i = 0; i < ainfo->num_attrs; ++i) {
10065 klass = ainfo->attrs [i].ctor->klass;
10066 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10073 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10076 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10077 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10082 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10088 mono_error_init (error);
10091 for (i = 0; i < ainfo->num_attrs; ++i) {
10092 klass = ainfo->attrs [i].ctor->klass;
10093 if (mono_class_has_parent (klass, attr_klass)) {
10098 if (attr_index == -1)
10101 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10102 if (!mono_error_ok (error))
10104 return mono_array_get (attrs, MonoObject*, attr_index);
10108 * mono_reflection_get_custom_attrs_info:
10109 * @obj: a reflection object handle
10111 * Return the custom attribute info for attributes defined for the
10112 * reflection handle @obj. The objects.
10114 * FIXME this function leaks like a sieve for SRE objects.
10116 MonoCustomAttrInfo*
10117 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10120 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10121 mono_error_assert_ok (&error);
10126 * mono_reflection_get_custom_attrs_info_checked:
10127 * @obj: a reflection object handle
10128 * @error: set on error
10130 * Return the custom attribute info for attributes defined for the
10131 * reflection handle @obj. The objects.
10133 * On failure returns NULL and sets @error.
10135 * FIXME this function leaks like a sieve for SRE objects.
10137 MonoCustomAttrInfo*
10138 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10141 MonoCustomAttrInfo *cinfo = NULL;
10143 mono_error_init (error);
10145 klass = obj->vtable->klass;
10146 if (klass == mono_defaults.monotype_class) {
10147 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10148 return_val_if_nok (error, NULL);
10149 klass = mono_class_from_mono_type (type);
10150 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10151 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10152 return_val_if_nok (error, NULL);
10153 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10154 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10155 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10156 return_val_if_nok (error, NULL);
10157 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10158 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10159 cinfo = mono_custom_attrs_from_module (module->image, error);
10160 return_val_if_nok (error, NULL);
10161 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10162 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10163 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10164 return_val_if_nok (error, NULL);
10165 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10166 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10167 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10168 return_val_if_nok (error, NULL);
10169 } else if (strcmp ("MonoField", klass->name) == 0) {
10170 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10171 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10172 return_val_if_nok (error, NULL);
10173 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10174 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10175 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10176 return_val_if_nok (error, NULL);
10177 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10178 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10179 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10180 return_val_if_nok (error, NULL);
10181 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10182 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10183 MonoClass *member_class = mono_object_class (param->MemberImpl);
10184 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10185 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10186 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10187 return_val_if_nok (error, NULL);
10188 } else if (is_sr_mono_property (member_class)) {
10189 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10190 MonoMethod *method;
10191 if (!(method = prop->property->get))
10192 method = prop->property->set;
10195 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10196 return_val_if_nok (error, NULL);
10198 #ifndef DISABLE_REFLECTION_EMIT
10199 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10200 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10201 return_val_if_nok (error, NULL);
10202 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10203 return_val_if_nok (error, NULL);
10204 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10205 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10206 MonoMethod *method = NULL;
10207 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10208 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10209 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10210 method = ((MonoReflectionMethod *)c->cb)->method;
10212 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));
10214 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10215 return_val_if_nok (error, NULL);
10219 char *type_name = mono_type_get_full_name (member_class);
10220 mono_error_set_generic_error (error, "System", "NotSupportedException",
10221 "Custom attributes on a ParamInfo with member %s are not supported",
10223 g_free (type_name);
10226 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10227 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10228 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10229 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10230 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10231 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10232 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10233 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10234 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10235 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10236 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10237 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10238 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10239 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10240 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10241 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10242 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10243 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10244 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10245 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10246 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10247 return_val_if_nok (error, NULL);
10248 } else { /* handle other types here... */
10249 g_error ("get custom attrs not yet supported for %s", klass->name);
10256 * mono_reflection_get_custom_attrs_by_type:
10257 * @obj: a reflection object handle
10259 * Return an array with all the custom attributes defined of the
10260 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10261 * of that type are returned. The objects are fully build. Return NULL if a loading error
10265 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10268 MonoCustomAttrInfo *cinfo;
10270 mono_error_init (error);
10272 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10273 return_val_if_nok (error, NULL);
10275 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10278 if (!cinfo->cached)
10279 mono_custom_attrs_free (cinfo);
10281 mono_loader_assert_no_error ();
10282 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10289 * mono_reflection_get_custom_attrs:
10290 * @obj: a reflection object handle
10292 * Return an array with all the custom attributes defined of the
10293 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10297 mono_reflection_get_custom_attrs (MonoObject *obj)
10301 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10305 * mono_reflection_get_custom_attrs_data:
10306 * @obj: a reflection obj handle
10308 * Returns an array of System.Reflection.CustomAttributeData,
10309 * which include information about attributes reflected on
10310 * types loaded using the Reflection Only methods
10313 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10317 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10318 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10323 * mono_reflection_get_custom_attrs_data_checked:
10324 * @obj: a reflection obj handle
10325 * @error: set on error
10327 * Returns an array of System.Reflection.CustomAttributeData,
10328 * which include information about attributes reflected on
10329 * types loaded using the Reflection Only methods
10332 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10335 MonoCustomAttrInfo *cinfo;
10337 mono_error_init (error);
10339 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10340 return_val_if_nok (error, NULL);
10342 result = mono_custom_attrs_data_construct (cinfo, error);
10343 return_val_if_nok (error, NULL);
10344 if (!cinfo->cached)
10345 mono_custom_attrs_free (cinfo);
10347 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10349 if (mono_loader_get_last_error ())
10350 mono_error_set_from_loader_error (error);
10355 static MonoReflectionType*
10356 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10358 static MonoMethod *method_get_underlying_system_type = NULL;
10359 MonoReflectionType *rt;
10360 MonoMethod *usertype_method;
10362 mono_error_init (error);
10364 if (!method_get_underlying_system_type)
10365 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10367 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10369 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10376 is_corlib_type (MonoClass *klass)
10378 return klass->image == mono_defaults.corlib;
10381 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10382 static MonoClass *cached_class; \
10383 if (cached_class) \
10384 return cached_class == _class; \
10385 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10386 cached_class = _class; \
10393 #ifndef DISABLE_REFLECTION_EMIT
10395 is_sre_array (MonoClass *klass)
10397 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10401 is_sre_byref (MonoClass *klass)
10403 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10407 is_sre_pointer (MonoClass *klass)
10409 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10413 is_sre_generic_instance (MonoClass *klass)
10415 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10419 is_sre_type_builder (MonoClass *klass)
10421 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10425 is_sre_method_builder (MonoClass *klass)
10427 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10431 is_sre_ctor_builder (MonoClass *klass)
10433 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10437 is_sre_field_builder (MonoClass *klass)
10439 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10443 is_sre_method_on_tb_inst (MonoClass *klass)
10445 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10449 is_sre_ctor_on_tb_inst (MonoClass *klass)
10451 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10455 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10458 mono_error_init (error);
10465 if (is_usertype (ref)) {
10466 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10467 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10473 klass = mono_object_class (ref);
10475 if (is_sre_array (klass)) {
10477 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10478 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10479 return_val_if_nok (error, NULL);
10481 if (sre_array->rank == 0) //single dimentional array
10482 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10484 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10485 sre_array->type.type = res;
10487 } else if (is_sre_byref (klass)) {
10489 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10490 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10491 return_val_if_nok (error, NULL);
10493 res = &mono_class_from_mono_type (base)->this_arg;
10494 sre_byref->type.type = res;
10496 } else if (is_sre_pointer (klass)) {
10498 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10499 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10500 return_val_if_nok (error, NULL);
10502 res = &mono_ptr_class_get (base)->byval_arg;
10503 sre_pointer->type.type = res;
10505 } else if (is_sre_generic_instance (klass)) {
10506 MonoType *res, **types;
10507 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10510 count = mono_array_length (gclass->type_arguments);
10511 types = g_new0 (MonoType*, count);
10512 for (i = 0; i < count; ++i) {
10513 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10514 types [i] = mono_reflection_type_get_handle (t, error);
10515 if (!types[i] || !is_ok (error)) {
10521 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10524 gclass->type.type = res;
10528 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10533 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10536 mono_reflection_type_get_handle (type, &error);
10537 mono_error_set_pending_exception (&error);
10541 mono_reflection_register_with_runtime (MonoReflectionType *type)
10544 MonoType *res = mono_reflection_type_get_handle (type, &error);
10545 mono_error_raise_exception (&error); /* FIXME don't raise here */
10546 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10550 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10552 klass = mono_class_from_mono_type (res);
10554 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10555 mono_domain_lock (domain);
10557 if (!image_is_dynamic (klass->image)) {
10558 mono_class_setup_supertypes (klass);
10560 if (!domain->type_hash)
10561 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10562 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10563 mono_g_hash_table_insert (domain->type_hash, res, type);
10565 mono_domain_unlock (domain);
10566 mono_loader_unlock ();
10570 * LOCKING: Assumes the loader lock is held.
10572 static MonoMethodSignature*
10573 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10575 MonoMethodSignature *sig;
10578 count = parameters? mono_array_length (parameters): 0;
10580 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10581 sig->param_count = count;
10582 sig->sentinelpos = -1; /* FIXME */
10583 for (i = 0; i < count; ++i) {
10584 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10585 mono_error_raise_exception (&error); /* FIXME don't raise here */
10591 * LOCKING: Assumes the loader lock is held.
10593 static MonoMethodSignature*
10594 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10595 MonoMethodSignature *sig;
10597 sig = parameters_to_signature (image, ctor->parameters);
10598 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10599 sig->ret = &mono_defaults.void_class->byval_arg;
10604 * LOCKING: Assumes the loader lock is held.
10606 static MonoMethodSignature*
10607 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10609 MonoMethodSignature *sig;
10611 sig = parameters_to_signature (image, method->parameters);
10612 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10613 if (method->rtype) {
10614 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10615 mono_error_raise_exception (&error); /* FIXME don't raise here */
10617 sig->ret = &mono_defaults.void_class->byval_arg;
10619 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10623 static MonoMethodSignature*
10624 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10626 MonoMethodSignature *sig;
10628 sig = parameters_to_signature (NULL, method->parameters);
10629 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10630 if (method->rtype) {
10631 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10632 mono_error_raise_exception (&error); /* FIXME don't raise here */
10634 sig->ret = &mono_defaults.void_class->byval_arg;
10636 sig->generic_param_count = 0;
10641 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10644 MonoClass *klass = mono_object_class (prop);
10645 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10646 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10647 *name = mono_string_to_utf8 (pb->name);
10648 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10649 mono_error_raise_exception (&error); /* FIXME don't raise here */
10651 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10652 *name = g_strdup (p->property->name);
10653 if (p->property->get)
10654 *type = mono_method_signature (p->property->get)->ret;
10656 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10661 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10664 MonoClass *klass = mono_object_class (field);
10665 if (strcmp (klass->name, "FieldBuilder") == 0) {
10666 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10667 *name = mono_string_to_utf8 (fb->name);
10668 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10669 mono_error_raise_exception (&error); /* FIXME don't raise here */
10671 MonoReflectionField *f = (MonoReflectionField *)field;
10672 *name = g_strdup (mono_field_get_name (f->field));
10673 *type = f->field->type;
10677 #else /* DISABLE_REFLECTION_EMIT */
10680 mono_reflection_register_with_runtime (MonoReflectionType *type)
10682 /* This is empty */
10686 is_sre_type_builder (MonoClass *klass)
10692 is_sre_generic_instance (MonoClass *klass)
10698 init_type_builder_generics (MonoObject *type)
10702 #endif /* !DISABLE_REFLECTION_EMIT */
10706 is_sr_mono_field (MonoClass *klass)
10708 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10712 is_sr_mono_property (MonoClass *klass)
10714 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10718 is_sr_mono_method (MonoClass *klass)
10720 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10724 is_sr_mono_cmethod (MonoClass *klass)
10726 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10730 is_sr_mono_generic_method (MonoClass *klass)
10732 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10736 is_sr_mono_generic_cmethod (MonoClass *klass)
10738 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10742 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10744 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10748 is_usertype (MonoReflectionType *ref)
10750 MonoClass *klass = mono_object_class (ref);
10751 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10754 static MonoReflectionType*
10755 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10757 mono_error_init (error);
10758 if (!type || type->type)
10761 if (is_usertype (type)) {
10762 type = mono_reflection_type_get_underlying_system_type (type, error);
10763 return_val_if_nok (error, NULL);
10764 if (is_usertype (type)) {
10765 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10773 * Encode a value in a custom attribute stream of bytes.
10774 * The value to encode is either supplied as an object in argument val
10775 * (valuetypes are boxed), or as a pointer to the data in the
10777 * @type represents the type of the value
10778 * @buffer is the start of the buffer
10779 * @p the current position in the buffer
10780 * @buflen contains the size of the buffer and is used to return the new buffer size
10781 * if this needs to be realloced.
10782 * @retbuffer and @retp return the start and the position of the buffer
10785 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10788 MonoTypeEnum simple_type;
10790 if ((p-buffer) + 10 >= *buflen) {
10793 newbuf = (char *)g_realloc (buffer, *buflen);
10794 p = newbuf + (p-buffer);
10798 argval = ((char*)arg + sizeof (MonoObject));
10799 simple_type = type->type;
10801 switch (simple_type) {
10802 case MONO_TYPE_BOOLEAN:
10807 case MONO_TYPE_CHAR:
10810 swap_with_size (p, argval, 2, 1);
10816 swap_with_size (p, argval, 4, 1);
10820 swap_with_size (p, argval, 8, 1);
10825 swap_with_size (p, argval, 8, 1);
10828 case MONO_TYPE_VALUETYPE:
10829 if (type->data.klass->enumtype) {
10830 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10833 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10836 case MONO_TYPE_STRING: {
10843 str = mono_string_to_utf8 ((MonoString*)arg);
10844 slen = strlen (str);
10845 if ((p-buffer) + 10 + slen >= *buflen) {
10849 newbuf = (char *)g_realloc (buffer, *buflen);
10850 p = newbuf + (p-buffer);
10853 mono_metadata_encode_value (slen, p, &p);
10854 memcpy (p, str, slen);
10859 case MONO_TYPE_CLASS: {
10862 MonoType *arg_type;
10868 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10869 mono_error_raise_exception (&error); /* FIXME don't raise here */
10870 str = type_get_qualified_name (arg_type, NULL);
10871 slen = strlen (str);
10872 if ((p-buffer) + 10 + slen >= *buflen) {
10876 newbuf = (char *)g_realloc (buffer, *buflen);
10877 p = newbuf + (p-buffer);
10880 mono_metadata_encode_value (slen, p, &p);
10881 memcpy (p, str, slen);
10886 case MONO_TYPE_SZARRAY: {
10888 MonoClass *eclass, *arg_eclass;
10891 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10894 len = mono_array_length ((MonoArray*)arg);
10896 *p++ = (len >> 8) & 0xff;
10897 *p++ = (len >> 16) & 0xff;
10898 *p++ = (len >> 24) & 0xff;
10900 *retbuffer = buffer;
10901 eclass = type->data.klass;
10902 arg_eclass = mono_object_class (arg)->element_class;
10905 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10906 eclass = mono_defaults.object_class;
10908 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10909 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10910 int elsize = mono_class_array_element_size (arg_eclass);
10911 for (i = 0; i < len; ++i) {
10912 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10915 } else if (eclass->valuetype && arg_eclass->valuetype) {
10916 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10917 int elsize = mono_class_array_element_size (eclass);
10918 for (i = 0; i < len; ++i) {
10919 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10923 for (i = 0; i < len; ++i) {
10924 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10929 case MONO_TYPE_OBJECT: {
10935 * The parameter type is 'object' but the type of the actual
10936 * argument is not. So we have to add type information to the blob
10937 * too. This is completely undocumented in the spec.
10941 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10946 klass = mono_object_class (arg);
10948 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10951 } else if (klass->enumtype) {
10953 } else if (klass == mono_defaults.string_class) {
10954 simple_type = MONO_TYPE_STRING;
10957 } else if (klass->rank == 1) {
10959 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10960 /* See Partition II, Appendix B3 */
10963 *p++ = klass->element_class->byval_arg.type;
10964 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10966 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10967 *p++ = simple_type = klass->byval_arg.type;
10970 g_error ("unhandled type in custom attr");
10972 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10973 slen = strlen (str);
10974 if ((p-buffer) + 10 + slen >= *buflen) {
10978 newbuf = (char *)g_realloc (buffer, *buflen);
10979 p = newbuf + (p-buffer);
10982 mono_metadata_encode_value (slen, p, &p);
10983 memcpy (p, str, slen);
10986 simple_type = mono_class_enum_basetype (klass)->type;
10990 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10993 *retbuffer = buffer;
10997 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10999 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11000 char *str = type_get_qualified_name (type, NULL);
11001 int slen = strlen (str);
11005 * This seems to be optional...
11008 mono_metadata_encode_value (slen, p, &p);
11009 memcpy (p, str, slen);
11012 } else if (type->type == MONO_TYPE_OBJECT) {
11014 } else if (type->type == MONO_TYPE_CLASS) {
11015 /* it should be a type: encode_cattr_value () has the check */
11018 mono_metadata_encode_value (type->type, p, &p);
11019 if (type->type == MONO_TYPE_SZARRAY)
11020 /* See the examples in Partition VI, Annex B */
11021 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11027 #ifndef DISABLE_REFLECTION_EMIT
11029 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11032 /* Preallocate a large enough buffer */
11033 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11034 char *str = type_get_qualified_name (type, NULL);
11035 len = strlen (str);
11037 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11038 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11039 len = strlen (str);
11044 len += strlen (name);
11046 if ((p-buffer) + 20 + len >= *buflen) {
11050 newbuf = (char *)g_realloc (buffer, *buflen);
11051 p = newbuf + (p-buffer);
11055 encode_field_or_prop_type (type, p, &p);
11057 len = strlen (name);
11058 mono_metadata_encode_value (len, p, &p);
11059 memcpy (p, name, len);
11061 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11063 *retbuffer = buffer;
11067 * mono_reflection_get_custom_attrs_blob:
11068 * @ctor: custom attribute constructor
11069 * @ctorArgs: arguments o the constructor
11075 * Creates the blob of data that needs to be saved in the metadata and that represents
11076 * the custom attributed described by @ctor, @ctorArgs etc.
11077 * Returns: a Byte array representing the blob of data.
11080 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11083 MonoMethodSignature *sig;
11088 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11089 /* sig is freed later so allocate it in the heap */
11090 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11092 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11095 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11097 p = buffer = (char *)g_malloc (buflen);
11098 /* write the prolog */
11101 for (i = 0; i < sig->param_count; ++i) {
11102 arg = mono_array_get (ctorArgs, MonoObject*, i);
11103 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11107 i += mono_array_length (properties);
11109 i += mono_array_length (fields);
11111 *p++ = (i >> 8) & 0xff;
11114 for (i = 0; i < mono_array_length (properties); ++i) {
11118 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11119 get_prop_name_and_type (prop, &pname, &ptype);
11120 *p++ = 0x54; /* PROPERTY signature */
11121 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11128 for (i = 0; i < mono_array_length (fields); ++i) {
11132 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11133 get_field_name_and_type (field, &fname, &ftype);
11134 *p++ = 0x53; /* FIELD signature */
11135 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11140 g_assert (p - buffer <= buflen);
11141 buflen = p - buffer;
11142 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11143 p = mono_array_addr (result, char, 0);
11144 memcpy (p, buffer, buflen);
11146 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11152 * mono_reflection_setup_internal_class:
11153 * @tb: a TypeBuilder object
11155 * Creates a MonoClass that represents the TypeBuilder.
11156 * This is a trick that lets us simplify a lot of reflection code
11157 * (and will allow us to support Build and Run assemblies easier).
11160 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11163 MonoClass *klass, *parent;
11165 RESOLVE_TYPE (tb->parent, &error);
11166 mono_error_raise_exception (&error); /* FIXME don't raise here */
11168 mono_loader_lock ();
11171 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11172 if (!is_ok (&error)) {
11173 mono_loader_unlock ();
11174 mono_error_raise_exception (&error); /* FIXME don't raise here */
11176 /* check so we can compile corlib correctly */
11177 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11178 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11179 parent = parent_type->data.klass;
11181 parent = mono_class_from_mono_type (parent_type);
11187 /* the type has already being created: it means we just have to change the parent */
11188 if (tb->type.type) {
11189 klass = mono_class_from_mono_type (tb->type.type);
11190 klass->parent = NULL;
11191 /* fool mono_class_setup_parent */
11192 klass->supertypes = NULL;
11193 mono_class_setup_parent (klass, parent);
11194 mono_class_setup_mono_type (klass);
11195 mono_loader_unlock ();
11199 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11201 klass->image = &tb->module->dynamic_image->image;
11203 klass->inited = 1; /* we lie to the runtime */
11204 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11205 if (!mono_error_ok (&error))
11207 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11208 if (!mono_error_ok (&error))
11210 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11211 klass->flags = tb->attrs;
11213 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11215 klass->element_class = klass;
11217 if (mono_class_get_ref_info (klass) == NULL) {
11219 mono_class_set_ref_info (klass, tb);
11221 /* Put into cache so mono_class_get_checked () will find it.
11222 Skip nested types as those should not be available on the global scope. */
11223 if (!tb->nesting_type)
11224 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11227 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11228 by performing a mono_class_get which does the full resolution.
11230 Working around this semantics would require us to write a lot of code for no clear advantage.
11232 mono_image_append_class_to_reflection_info_set (klass);
11234 g_assert (mono_class_get_ref_info (klass) == tb);
11237 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11239 if (parent != NULL) {
11240 mono_class_setup_parent (klass, parent);
11241 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11242 const char *old_n = klass->name;
11243 /* trick to get relative numbering right when compiling corlib */
11244 klass->name = "BuildingObject";
11245 mono_class_setup_parent (klass, mono_defaults.object_class);
11246 klass->name = old_n;
11249 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11250 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11251 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11252 klass->instance_size = sizeof (MonoObject);
11253 klass->size_inited = 1;
11254 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11257 mono_class_setup_mono_type (klass);
11259 mono_class_setup_supertypes (klass);
11262 * FIXME: handle interfaces.
11265 tb->type.type = &klass->byval_arg;
11267 if (tb->nesting_type) {
11268 g_assert (tb->nesting_type->type);
11269 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11270 if (!is_ok (&error)) goto failure;
11271 klass->nested_in = mono_class_from_mono_type (nesting_type);
11274 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11276 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11278 mono_loader_unlock ();
11282 mono_loader_unlock ();
11283 mono_error_raise_exception (&error);
11287 * mono_reflection_setup_generic_class:
11288 * @tb: a TypeBuilder object
11290 * Setup the generic class before adding the first generic parameter.
11293 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11298 * mono_reflection_create_generic_class:
11299 * @tb: a TypeBuilder object
11301 * Creates the generic class after all generic parameters have been added.
11304 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11310 klass = mono_class_from_mono_type (tb->type.type);
11312 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11314 if (klass->generic_container || (count == 0))
11317 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11319 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11321 klass->generic_container->owner.klass = klass;
11322 klass->generic_container->type_argc = count;
11323 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11325 klass->is_generic = 1;
11327 for (i = 0; i < count; i++) {
11328 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11329 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11330 mono_error_raise_exception (&error); /* FIXME don't raise here */
11331 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11332 klass->generic_container->type_params [i] = *param;
11333 /*Make sure we are a diferent type instance */
11334 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11335 klass->generic_container->type_params [i].info.pklass = NULL;
11336 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11338 g_assert (klass->generic_container->type_params [i].param.owner);
11341 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11345 * mono_reflection_create_internal_class:
11346 * @tb: a TypeBuilder object
11348 * Actually create the MonoClass that is associated with the TypeBuilder.
11351 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11356 klass = mono_class_from_mono_type (tb->type.type);
11358 mono_loader_lock ();
11359 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11360 MonoReflectionFieldBuilder *fb;
11362 MonoType *enum_basetype;
11364 g_assert (tb->fields != NULL);
11365 g_assert (mono_array_length (tb->fields) >= 1);
11367 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11369 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11370 if (!is_ok (&error)) {
11371 mono_loader_unlock ();
11372 mono_error_raise_exception (&error); /* FIXME don't raise here */
11374 if (!mono_type_is_valid_enum_basetype (field_type)) {
11375 mono_loader_unlock ();
11379 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11380 if (!is_ok (&error)) {
11381 mono_loader_unlock ();
11382 mono_error_raise_exception (&error); /* FIXME don't raise here */
11384 klass->element_class = mono_class_from_mono_type (enum_basetype);
11385 if (!klass->element_class)
11386 klass->element_class = mono_class_from_mono_type (enum_basetype);
11389 * get the element_class from the current corlib.
11391 ec = default_class_from_mono_type (enum_basetype);
11392 klass->instance_size = ec->instance_size;
11393 klass->size_inited = 1;
11395 * this is almost safe to do with enums and it's needed to be able
11396 * to create objects of the enum type (for use in SetConstant).
11398 /* FIXME: Does this mean enums can't have method overrides ? */
11399 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11401 mono_loader_unlock ();
11404 static MonoMarshalSpec*
11405 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11406 MonoReflectionMarshal *minfo)
11409 MonoMarshalSpec *res;
11411 res = image_g_new0 (image, MonoMarshalSpec, 1);
11412 res->native = (MonoMarshalNative)minfo->type;
11414 switch (minfo->type) {
11415 case MONO_NATIVE_LPARRAY:
11416 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11417 if (minfo->has_size) {
11418 res->data.array_data.param_num = minfo->param_num;
11419 res->data.array_data.num_elem = minfo->count;
11420 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11423 res->data.array_data.param_num = -1;
11424 res->data.array_data.num_elem = -1;
11425 res->data.array_data.elem_mult = -1;
11429 case MONO_NATIVE_BYVALTSTR:
11430 case MONO_NATIVE_BYVALARRAY:
11431 res->data.array_data.num_elem = minfo->count;
11434 case MONO_NATIVE_CUSTOM:
11435 if (minfo->marshaltyperef) {
11436 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11437 mono_error_raise_exception (&error); /* FIXME don't raise here */
11438 res->data.custom_data.custom_name =
11439 type_get_fully_qualified_name (marshaltyperef);
11441 if (minfo->mcookie)
11442 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11451 #endif /* !DISABLE_REFLECTION_EMIT */
11453 MonoReflectionMarshalAsAttribute*
11454 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11455 MonoMarshalSpec *spec, MonoError *error)
11457 MonoReflectionType *rt;
11458 MonoReflectionMarshalAsAttribute *minfo;
11461 mono_error_init (error);
11463 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11466 minfo->utype = spec->native;
11468 switch (minfo->utype) {
11469 case MONO_NATIVE_LPARRAY:
11470 minfo->array_subtype = spec->data.array_data.elem_type;
11471 minfo->size_const = spec->data.array_data.num_elem;
11472 if (spec->data.array_data.param_num != -1)
11473 minfo->size_param_index = spec->data.array_data.param_num;
11476 case MONO_NATIVE_BYVALTSTR:
11477 case MONO_NATIVE_BYVALARRAY:
11478 minfo->size_const = spec->data.array_data.num_elem;
11481 case MONO_NATIVE_CUSTOM:
11482 if (spec->data.custom_data.custom_name) {
11483 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11485 rt = mono_type_get_object_checked (domain, mtype, error);
11489 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11492 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11494 if (spec->data.custom_data.cookie)
11495 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11505 #ifndef DISABLE_REFLECTION_EMIT
11507 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11508 ReflectionMethodBuilder *rmb,
11509 MonoMethodSignature *sig)
11513 MonoMethodWrapper *wrapperm;
11514 MonoMarshalSpec **specs;
11515 MonoReflectionMethodAux *method_aux;
11520 mono_error_init (&error);
11522 * Methods created using a MethodBuilder should have their memory allocated
11523 * inside the image mempool, while dynamic methods should have their memory
11526 dynamic = rmb->refs != NULL;
11527 image = dynamic ? NULL : klass->image;
11530 g_assert (!klass->generic_class);
11532 mono_loader_lock ();
11534 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11535 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11536 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11538 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11540 wrapperm = (MonoMethodWrapper*)m;
11542 m->dynamic = dynamic;
11544 m->flags = rmb->attrs;
11545 m->iflags = rmb->iattrs;
11546 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11548 m->signature = sig;
11549 m->sre_method = TRUE;
11550 m->skip_visibility = rmb->skip_visibility;
11551 if (rmb->table_idx)
11552 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11554 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11555 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11556 m->string_ctor = 1;
11558 m->signature->pinvoke = 1;
11559 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11560 m->signature->pinvoke = 1;
11562 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11564 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11565 g_assert (mono_error_ok (&error));
11566 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11567 g_assert (mono_error_ok (&error));
11569 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11571 if (image_is_dynamic (klass->image))
11572 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11574 mono_loader_unlock ();
11577 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11578 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11579 MonoMethodHeader *header;
11581 gint32 max_stack, i;
11582 gint32 num_locals = 0;
11583 gint32 num_clauses = 0;
11587 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11588 code_size = rmb->ilgen->code_len;
11589 max_stack = rmb->ilgen->max_stack;
11590 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11591 if (rmb->ilgen->ex_handlers)
11592 num_clauses = method_count_clauses (rmb->ilgen);
11595 code = mono_array_addr (rmb->code, guint8, 0);
11596 code_size = mono_array_length (rmb->code);
11597 /* we probably need to run a verifier on the code... */
11607 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11608 header->code_size = code_size;
11609 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11610 memcpy ((char*)header->code, code, code_size);
11611 header->max_stack = max_stack;
11612 header->init_locals = rmb->init_locals;
11613 header->num_locals = num_locals;
11615 for (i = 0; i < num_locals; ++i) {
11616 MonoReflectionLocalBuilder *lb =
11617 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11619 header->locals [i] = image_g_new0 (image, MonoType, 1);
11620 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11621 mono_error_assert_ok (&error);
11622 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11625 header->num_clauses = num_clauses;
11627 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11628 rmb->ilgen, num_clauses, &error);
11629 mono_error_assert_ok (&error);
11632 wrapperm->header = header;
11635 if (rmb->generic_params) {
11636 int count = mono_array_length (rmb->generic_params);
11637 MonoGenericContainer *container = rmb->generic_container;
11639 g_assert (container);
11641 container->type_argc = count;
11642 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11643 container->owner.method = m;
11644 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11646 m->is_generic = TRUE;
11647 mono_method_set_generic_container (m, container);
11649 for (i = 0; i < count; i++) {
11650 MonoReflectionGenericParam *gp =
11651 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11652 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11653 mono_error_assert_ok (&error);
11654 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11655 container->type_params [i] = *param;
11659 * The method signature might have pointers to generic parameters that belong to other methods.
11660 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11661 * generic parameters.
11663 for (i = 0; i < m->signature->param_count; ++i) {
11664 MonoType *t = m->signature->params [i];
11665 if (t->type == MONO_TYPE_MVAR) {
11666 MonoGenericParam *gparam = t->data.generic_param;
11667 if (gparam->num < count) {
11668 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11669 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11675 if (klass->generic_container) {
11676 container->parent = klass->generic_container;
11677 container->context.class_inst = klass->generic_container->context.class_inst;
11679 container->context.method_inst = mono_get_shared_generic_inst (container);
11683 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11687 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11689 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11690 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11691 for (i = 0; i < rmb->nrefs; ++i)
11692 data [i + 1] = rmb->refs [i];
11697 /* Parameter info */
11700 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11701 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11702 for (i = 0; i <= m->signature->param_count; ++i) {
11703 MonoReflectionParamBuilder *pb;
11704 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11705 if ((i > 0) && (pb->attrs)) {
11706 /* Make a copy since it might point to a shared type structure */
11707 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11708 m->signature->params [i - 1]->attrs = pb->attrs;
11711 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11712 MonoDynamicImage *assembly;
11714 MonoTypeEnum def_type;
11718 if (!method_aux->param_defaults) {
11719 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11720 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11722 assembly = (MonoDynamicImage*)klass->image;
11723 idx = encode_constant (assembly, pb->def_value, &def_type);
11724 /* Copy the data from the blob since it might get realloc-ed */
11725 p = assembly->blob.data + idx;
11726 len = mono_metadata_decode_blob_size (p, &p2);
11728 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11729 method_aux->param_default_types [i] = def_type;
11730 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11734 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11735 g_assert (mono_error_ok (&error));
11738 if (!method_aux->param_cattr)
11739 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11740 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11746 /* Parameter marshalling */
11749 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11750 MonoReflectionParamBuilder *pb;
11751 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11752 if (pb->marshal_info) {
11754 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11755 specs [pb->position] =
11756 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11760 if (specs != NULL) {
11762 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11763 method_aux->param_marshall = specs;
11766 if (image_is_dynamic (klass->image) && method_aux)
11767 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11769 mono_loader_unlock ();
11775 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11777 ReflectionMethodBuilder rmb;
11778 MonoMethodSignature *sig;
11780 mono_loader_lock ();
11781 sig = ctor_builder_to_signature (klass->image, mb);
11782 mono_loader_unlock ();
11784 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11787 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11788 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11790 /* If we are in a generic class, we might be called multiple times from inflate_method */
11791 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11792 /* ilgen is no longer needed */
11796 return mb->mhandle;
11800 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11802 ReflectionMethodBuilder rmb;
11803 MonoMethodSignature *sig;
11805 mono_error_init (error);
11807 mono_loader_lock ();
11808 sig = method_builder_to_signature (klass->image, mb);
11809 mono_loader_unlock ();
11811 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11814 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11815 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11817 /* If we are in a generic class, we might be called multiple times from inflate_method */
11818 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11819 /* ilgen is no longer needed */
11822 return mb->mhandle;
11825 static MonoClassField*
11826 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11828 MonoClassField *field;
11832 field = g_new0 (MonoClassField, 1);
11834 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11835 g_assert (mono_error_ok (&error));
11836 if (fb->attrs || fb->modreq || fb->modopt) {
11837 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11838 if (!is_ok (&error)) {
11840 mono_error_raise_exception (&error); /* FIXME don't raise here */
11842 field->type = mono_metadata_type_dup (NULL, type);
11843 field->type->attrs = fb->attrs;
11845 g_assert (image_is_dynamic (klass->image));
11846 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11847 g_free (field->type);
11848 field->type = mono_metadata_type_dup (klass->image, custom);
11851 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11852 if (!is_ok (&error)) {
11854 mono_error_raise_exception (&error); /* FIXME don't raise here */
11857 if (fb->offset != -1)
11858 field->offset = fb->offset;
11859 field->parent = klass;
11860 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11862 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11869 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11873 MonoReflectionTypeBuilder *tb = NULL;
11874 gboolean is_dynamic = FALSE;
11875 MonoClass *geninst;
11877 mono_loader_lock ();
11879 if (is_sre_type_builder (mono_object_class (type))) {
11880 tb = (MonoReflectionTypeBuilder *) type;
11883 } else if (is_sre_generic_instance (mono_object_class (type))) {
11884 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11885 MonoReflectionType *gtd = rgi->generic_type;
11887 if (is_sre_type_builder (mono_object_class (gtd))) {
11888 tb = (MonoReflectionTypeBuilder *)gtd;
11893 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11894 if (tb && tb->generic_container)
11895 mono_reflection_create_generic_class (tb);
11897 MonoType *t = mono_reflection_type_get_handle (type, &error);
11898 mono_error_raise_exception (&error); /* FIXME don't raise here */
11900 klass = mono_class_from_mono_type (t);
11901 if (!klass->generic_container) {
11902 mono_loader_unlock ();
11906 if (klass->wastypebuilder) {
11907 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11912 mono_loader_unlock ();
11914 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11916 return &geninst->byval_arg;
11920 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11922 MonoGenericClass *gclass;
11923 MonoGenericInst *inst;
11925 g_assert (klass->generic_container);
11927 inst = mono_metadata_get_generic_inst (type_argc, types);
11928 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11930 return mono_generic_class_get_class (gclass);
11933 MonoReflectionMethod*
11934 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11938 MonoMethod *method, *inflated;
11939 MonoMethodInflated *imethod;
11940 MonoGenericContext tmp_context;
11941 MonoGenericInst *ginst;
11942 MonoType **type_argv;
11945 /*FIXME but this no longer should happen*/
11946 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11947 #ifndef DISABLE_REFLECTION_EMIT
11948 MonoReflectionMethodBuilder *mb = NULL;
11952 mb = (MonoReflectionMethodBuilder *) rmethod;
11953 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11954 mono_error_raise_exception (&error); /* FIXME don't raise here */
11955 klass = mono_class_from_mono_type (tb);
11957 method = methodbuilder_to_mono_method (klass, mb, &error);
11959 mono_error_raise_exception (&error); /* FIXME don't raise here */
11961 g_assert_not_reached ();
11965 method = rmethod->method;
11968 klass = method->klass;
11970 if (method->is_inflated)
11971 method = ((MonoMethodInflated *) method)->declaring;
11973 count = mono_method_signature (method)->generic_param_count;
11974 if (count != mono_array_length (types))
11977 type_argv = g_new0 (MonoType *, count);
11978 for (i = 0; i < count; i++) {
11979 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11980 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11981 if (!is_ok (&error)) {
11982 g_free (type_argv);
11983 mono_error_raise_exception (&error); /* FIXME don't raise here */
11986 ginst = mono_metadata_get_generic_inst (count, type_argv);
11987 g_free (type_argv);
11989 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11990 tmp_context.method_inst = ginst;
11992 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11993 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11994 imethod = (MonoMethodInflated *) inflated;
11996 /*FIXME but I think this is no longer necessary*/
11997 if (image_is_dynamic (method->klass->image)) {
11998 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12000 * This table maps metadata structures representing inflated methods/fields
12001 * to the reflection objects representing their generic definitions.
12003 mono_image_lock ((MonoImage*)image);
12004 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12005 mono_image_unlock ((MonoImage*)image);
12008 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12009 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12011 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12012 mono_error_raise_exception (&error); /* FIXME don't raise here */
12016 #ifndef DISABLE_REFLECTION_EMIT
12018 static MonoMethod *
12019 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12021 MonoMethodInflated *imethod;
12022 MonoGenericContext *context;
12026 * With generic code sharing the klass might not be inflated.
12027 * This can happen because classes inflated with their own
12028 * type arguments are "normalized" to the uninflated class.
12030 if (!klass->generic_class)
12033 context = mono_class_get_context (klass);
12035 if (klass->method.count && klass->methods) {
12036 /* Find the already created inflated method */
12037 for (i = 0; i < klass->method.count; ++i) {
12038 g_assert (klass->methods [i]->is_inflated);
12039 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12042 g_assert (i < klass->method.count);
12043 imethod = (MonoMethodInflated*)klass->methods [i];
12046 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12047 mono_error_assert_ok (&error);
12050 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12051 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12053 mono_image_lock ((MonoImage*)image);
12054 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12055 mono_image_unlock ((MonoImage*)image);
12057 return (MonoMethod *) imethod;
12060 static MonoMethod *
12061 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12063 MonoMethod *method;
12066 mono_error_init (error);
12068 MonoClass *type_class = mono_object_class (type);
12070 if (is_sre_generic_instance (type_class)) {
12071 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12072 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12073 return_val_if_nok (error, NULL);
12074 gklass = mono_class_from_mono_type (generic_type);
12075 } else if (is_sre_type_builder (type_class)) {
12076 MonoType *t = mono_reflection_type_get_handle (type, error);
12077 return_val_if_nok (error, NULL);
12078 gklass = mono_class_from_mono_type (t);
12079 } else if (type->type) {
12080 gklass = mono_class_from_mono_type (type->type);
12081 gklass = mono_class_get_generic_type_definition (gklass);
12083 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12086 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12087 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12088 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12090 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12094 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12095 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12098 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12099 method = ((MonoReflectionMethod *) obj)->method;
12101 method = NULL; /* prevent compiler warning */
12102 g_error ("can't handle type %s", obj->vtable->klass->name);
12105 MonoType *t = mono_reflection_type_get_handle (type, error);
12106 return_val_if_nok (error, NULL);
12107 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12110 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12112 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12115 MonoGenericClass *gclass;
12116 MonoDynamicGenericClass *dgclass;
12117 MonoClass *klass, *gklass;
12121 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12122 mono_error_raise_exception (&error); /* FIXME don't raise here */
12123 klass = mono_class_from_mono_type (gtype);
12124 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12125 gclass = gtype->data.generic_class;
12127 if (!gclass->is_dynamic)
12130 dgclass = (MonoDynamicGenericClass *) gclass;
12132 if (dgclass->initialized)
12135 gklass = gclass->container_class;
12136 mono_class_init (gklass);
12138 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12140 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12141 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12142 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12144 for (i = 0; i < dgclass->count_fields; i++) {
12146 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12147 MonoClassField *field, *inflated_field = NULL;
12149 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12150 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12151 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12152 field = ((MonoReflectionField *) obj)->field;
12154 field = NULL; /* prevent compiler warning */
12155 g_assert_not_reached ();
12158 dgclass->fields [i] = *field;
12159 dgclass->fields [i].parent = klass;
12160 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12161 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12162 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12163 dgclass->field_generic_types [i] = field->type;
12164 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12165 dgclass->field_objects [i] = obj;
12167 if (inflated_field) {
12168 g_free (inflated_field);
12170 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12174 dgclass->initialized = TRUE;
12178 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12180 MonoDynamicGenericClass *dgclass;
12183 g_assert (gclass->is_dynamic);
12185 dgclass = (MonoDynamicGenericClass *)gclass;
12187 for (i = 0; i < dgclass->count_fields; ++i) {
12188 MonoClassField *field = dgclass->fields + i;
12189 mono_metadata_free_type (field->type);
12190 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12195 fix_partial_generic_class (MonoClass *klass)
12197 MonoClass *gklass = klass->generic_class->container_class;
12198 MonoDynamicGenericClass *dgclass;
12201 if (klass->wastypebuilder)
12204 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12205 if (klass->parent != gklass->parent) {
12207 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12208 if (mono_error_ok (&error)) {
12209 MonoClass *parent = mono_class_from_mono_type (parent_type);
12210 mono_metadata_free_type (parent_type);
12211 if (parent != klass->parent) {
12212 /*fool mono_class_setup_parent*/
12213 klass->supertypes = NULL;
12214 mono_class_setup_parent (klass, parent);
12217 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12218 mono_error_cleanup (&error);
12219 if (gklass->wastypebuilder)
12220 klass->wastypebuilder = TRUE;
12225 if (!dgclass->initialized)
12228 if (klass->method.count != gklass->method.count) {
12229 klass->method.count = gklass->method.count;
12230 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12232 for (i = 0; i < klass->method.count; i++) {
12234 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12235 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12236 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12240 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12241 klass->interface_count = gklass->interface_count;
12242 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12243 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12245 for (i = 0; i < gklass->interface_count; ++i) {
12247 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12248 mono_error_raise_exception (&error); /* FIXME don't raise here */
12250 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12251 mono_metadata_free_type (iface_type);
12253 ensure_runtime_vtable (klass->interfaces [i], &error);
12254 mono_error_raise_exception (&error); /* FIXME don't raise here */
12256 klass->interfaces_inited = 1;
12259 if (klass->field.count != gklass->field.count) {
12260 klass->field.count = gklass->field.count;
12261 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12263 for (i = 0; i < klass->field.count; i++) {
12265 klass->fields [i] = gklass->fields [i];
12266 klass->fields [i].parent = klass;
12267 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12268 mono_error_raise_exception (&error); /* FIXME don't raise here */
12272 /*We can only finish with this klass once it's parent has as well*/
12273 if (gklass->wastypebuilder)
12274 klass->wastypebuilder = TRUE;
12279 * ensure_generic_class_runtime_vtable:
12280 * @klass a generic class
12281 * @error set on error
12283 * Ensures that the generic container of @klass has a vtable and
12284 * returns TRUE on success. On error returns FALSE and sets @error.
12287 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12289 MonoClass *gklass = klass->generic_class->container_class;
12291 mono_error_init (error);
12293 if (!ensure_runtime_vtable (gklass, error))
12296 fix_partial_generic_class (klass);
12302 * ensure_runtime_vtable:
12304 * @error set on error
12306 * Ensures that @klass has a vtable and returns TRUE on success. On
12307 * error returns FALSE and sets @error.
12310 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12312 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12315 mono_error_init (error);
12317 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12320 if (!ensure_runtime_vtable (klass->parent, error))
12324 num = tb->ctors? mono_array_length (tb->ctors): 0;
12325 num += tb->num_methods;
12326 klass->method.count = num;
12327 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12328 num = tb->ctors? mono_array_length (tb->ctors): 0;
12329 for (i = 0; i < num; ++i) {
12330 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12333 klass->methods [i] = ctor;
12335 num = tb->num_methods;
12337 for (i = 0; i < num; ++i) {
12338 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12341 klass->methods [j++] = meth;
12344 if (tb->interfaces) {
12345 klass->interface_count = mono_array_length (tb->interfaces);
12346 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12347 for (i = 0; i < klass->interface_count; ++i) {
12348 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12349 return_val_if_nok (error, FALSE);
12350 klass->interfaces [i] = mono_class_from_mono_type (iface);
12351 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12354 klass->interfaces_inited = 1;
12356 } else if (klass->generic_class){
12357 if (!ensure_generic_class_runtime_vtable (klass, error))
12361 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12363 for (i = 0; i < klass->method.count; ++i) {
12364 MonoMethod *im = klass->methods [i];
12365 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12366 im->slot = slot_num++;
12369 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12370 mono_class_setup_interface_offsets (klass);
12371 mono_class_setup_interface_id (klass);
12375 * The generic vtable is needed even if image->run is not set since some
12376 * runtime code like ves_icall_Type_GetMethodsByName depends on
12377 * method->slot being defined.
12381 * tb->methods could not be freed since it is used for determining
12382 * overrides during dynamic vtable construction.
12389 mono_reflection_method_get_handle (MonoObject *method)
12392 MonoClass *klass = mono_object_class (method);
12393 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12394 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12395 return sr_method->method;
12397 if (is_sre_method_builder (klass)) {
12398 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12399 return mb->mhandle;
12401 if (is_sre_method_on_tb_inst (klass)) {
12402 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12403 MonoMethod *result;
12404 /*FIXME move this to a proper method and unify with resolve_object*/
12405 if (m->method_args) {
12406 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12407 mono_error_raise_exception (&error); /* FIXME don't raise here */
12409 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12410 mono_error_raise_exception (&error); /* FIXME don't raise here */
12411 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12412 MonoMethod *mono_method;
12414 if (is_sre_method_builder (mono_object_class (m->mb)))
12415 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12416 else if (is_sr_mono_method (mono_object_class (m->mb)))
12417 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12419 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)));
12421 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12426 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12431 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12433 MonoReflectionTypeBuilder *tb;
12435 MonoReflectionMethod *m;
12438 *num_overrides = 0;
12440 g_assert (image_is_dynamic (klass->image));
12442 if (!mono_class_get_ref_info (klass))
12445 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12447 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12451 for (i = 0; i < tb->num_methods; ++i) {
12452 MonoReflectionMethodBuilder *mb =
12453 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12454 if (mb->override_methods)
12455 onum += mono_array_length (mb->override_methods);
12460 *overrides = g_new0 (MonoMethod*, onum * 2);
12463 for (i = 0; i < tb->num_methods; ++i) {
12464 MonoReflectionMethodBuilder *mb =
12465 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12466 if (mb->override_methods) {
12467 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12468 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12470 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12471 (*overrides) [onum * 2 + 1] = mb->mhandle;
12473 g_assert (mb->mhandle);
12481 *num_overrides = onum;
12485 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12487 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12488 MonoReflectionFieldBuilder *fb;
12489 MonoClassField *field;
12490 MonoImage *image = klass->image;
12491 const char *p, *p2;
12493 guint32 len, idx, real_size = 0;
12495 klass->field.count = tb->num_fields;
12496 klass->field.first = 0;
12498 mono_error_init (error);
12500 if (tb->class_size) {
12501 if ((tb->packing_size & 0xffffff00) != 0) {
12502 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12503 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12506 klass->packing_size = tb->packing_size;
12507 real_size = klass->instance_size + tb->class_size;
12510 if (!klass->field.count) {
12511 klass->instance_size = MAX (klass->instance_size, real_size);
12515 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12516 mono_class_alloc_ext (klass);
12517 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12519 This is, guess what, a hack.
12520 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12521 On the static path no field class is resolved, only types are built. This is the right thing to do
12523 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12525 klass->size_inited = 1;
12527 for (i = 0; i < klass->field.count; ++i) {
12528 MonoArray *rva_data;
12529 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12530 field = &klass->fields [i];
12531 field->name = mono_string_to_utf8_image (image, fb->name, error);
12532 if (!mono_error_ok (error))
12535 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12536 return_if_nok (error);
12537 field->type = mono_metadata_type_dup (klass->image, type);
12538 field->type->attrs = fb->attrs;
12540 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12541 return_if_nok (error);
12544 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12545 char *base = mono_array_addr (rva_data, char, 0);
12546 size_t size = mono_array_length (rva_data);
12547 char *data = (char *)mono_image_alloc (klass->image, size);
12548 memcpy (data, base, size);
12549 klass->ext->field_def_values [i].data = data;
12551 if (fb->offset != -1)
12552 field->offset = fb->offset;
12553 field->parent = klass;
12554 fb->handle = field;
12555 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12557 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12558 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12560 if (fb->def_value) {
12561 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12562 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12563 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12564 /* Copy the data from the blob since it might get realloc-ed */
12565 p = assembly->blob.data + idx;
12566 len = mono_metadata_decode_blob_size (p, &p2);
12568 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12569 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12573 klass->instance_size = MAX (klass->instance_size, real_size);
12574 mono_class_layout_fields (klass);
12578 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12581 MonoReflectionPropertyBuilder *pb;
12582 MonoImage *image = klass->image;
12583 MonoProperty *properties;
12586 mono_error_init (error);
12589 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12591 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12592 klass->ext->property.first = 0;
12594 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12595 klass->ext->properties = properties;
12596 for (i = 0; i < klass->ext->property.count; ++i) {
12597 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12598 properties [i].parent = klass;
12599 properties [i].attrs = pb->attrs;
12600 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12601 if (!mono_error_ok (error))
12603 if (pb->get_method)
12604 properties [i].get = pb->get_method->mhandle;
12605 if (pb->set_method)
12606 properties [i].set = pb->set_method->mhandle;
12608 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12609 if (pb->def_value) {
12611 const char *p, *p2;
12612 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12613 if (!klass->ext->prop_def_values)
12614 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12615 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12616 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12617 /* Copy the data from the blob since it might get realloc-ed */
12618 p = assembly->blob.data + idx;
12619 len = mono_metadata_decode_blob_size (p, &p2);
12621 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12622 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12627 MonoReflectionEvent *
12628 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12631 MonoEvent *event = g_new0 (MonoEvent, 1);
12634 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12635 mono_error_raise_exception (&error); /* FIXME don't raise here */
12636 klass = mono_class_from_mono_type (type);
12638 event->parent = klass;
12639 event->attrs = eb->attrs;
12640 event->name = mono_string_to_utf8 (eb->name);
12641 if (eb->add_method)
12642 event->add = eb->add_method->mhandle;
12643 if (eb->remove_method)
12644 event->remove = eb->remove_method->mhandle;
12645 if (eb->raise_method)
12646 event->raise = eb->raise_method->mhandle;
12648 #ifndef MONO_SMALL_CONFIG
12649 if (eb->other_methods) {
12651 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12652 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12653 MonoReflectionMethodBuilder *mb =
12654 mono_array_get (eb->other_methods,
12655 MonoReflectionMethodBuilder*, j);
12656 event->other [j] = mb->mhandle;
12661 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12662 mono_error_raise_exception (&error); /* FIXME don't raise here */
12667 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12669 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12670 MonoReflectionEventBuilder *eb;
12671 MonoImage *image = klass->image;
12675 mono_error_init (error);
12678 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12680 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12681 klass->ext->event.first = 0;
12683 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12684 klass->ext->events = events;
12685 for (i = 0; i < klass->ext->event.count; ++i) {
12686 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12687 events [i].parent = klass;
12688 events [i].attrs = eb->attrs;
12689 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12690 if (!mono_error_ok (error))
12692 if (eb->add_method)
12693 events [i].add = eb->add_method->mhandle;
12694 if (eb->remove_method)
12695 events [i].remove = eb->remove_method->mhandle;
12696 if (eb->raise_method)
12697 events [i].raise = eb->raise_method->mhandle;
12699 #ifndef MONO_SMALL_CONFIG
12700 if (eb->other_methods) {
12702 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12703 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12704 MonoReflectionMethodBuilder *mb =
12705 mono_array_get (eb->other_methods,
12706 MonoReflectionMethodBuilder*, j);
12707 events [i].other [j] = mb->mhandle;
12711 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12716 remove_instantiations_of_and_ensure_contents (gpointer key,
12718 gpointer user_data)
12720 MonoType *type = (MonoType*)key;
12721 MonoClass *klass = (MonoClass*)user_data;
12723 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12724 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12731 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12733 mono_error_init (error);
12739 for (i = 0; i < mono_array_length (arr); ++i) {
12740 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12741 if (!mono_error_ok (error))
12746 MonoReflectionType*
12747 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12751 MonoDomain* domain;
12752 MonoReflectionType* res;
12755 domain = mono_object_domain (tb);
12756 klass = mono_class_from_mono_type (tb->type.type);
12759 * Check for user defined Type subclasses.
12761 RESOLVE_TYPE (tb->parent, &error);
12762 mono_error_raise_exception (&error); /* FIXME don't raise here */
12763 check_array_for_usertypes (tb->interfaces, &error);
12764 mono_error_raise_exception (&error); /*FIXME don't raise here */
12766 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12767 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12769 RESOLVE_TYPE (fb->type, &error);
12770 mono_error_raise_exception (&error); /* FIXME don't raise here */
12771 check_array_for_usertypes (fb->modreq, &error);
12772 mono_error_raise_exception (&error); /*FIXME don't raise here */
12773 check_array_for_usertypes (fb->modopt, &error);
12774 mono_error_raise_exception (&error); /*FIXME don't raise here */
12775 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12776 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12777 mono_error_raise_exception (&error); /* FIXME don't raise here */
12783 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12784 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12786 RESOLVE_TYPE (mb->rtype, &error);
12787 mono_error_raise_exception (&error); /* FIXME don't raise here */
12788 check_array_for_usertypes (mb->return_modreq, &error);
12789 mono_error_raise_exception (&error); /*FIXME don't raise here */
12790 check_array_for_usertypes (mb->return_modopt, &error);
12791 mono_error_raise_exception (&error); /*FIXME don't raise here */
12792 check_array_for_usertypes (mb->parameters, &error);
12793 mono_error_raise_exception (&error); /*FIXME don't raise here */
12794 if (mb->param_modreq)
12795 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12796 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12797 mono_error_raise_exception (&error); /*FIXME don't raise here */
12799 if (mb->param_modopt)
12800 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12801 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12802 mono_error_raise_exception (&error); /*FIXME don't raise here */
12808 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12809 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12811 check_array_for_usertypes (mb->parameters, &error);
12812 mono_error_raise_exception (&error); /*FIXME don't raise here */
12813 if (mb->param_modreq)
12814 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12815 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12816 mono_error_raise_exception (&error); /*FIXME don't raise here */
12818 if (mb->param_modopt)
12819 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12820 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12821 mono_error_raise_exception (&error); /*FIXME don't raise here */
12827 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12830 * we need to lock the domain because the lock will be taken inside
12831 * So, we need to keep the locking order correct.
12833 mono_loader_lock ();
12834 mono_domain_lock (domain);
12835 if (klass->wastypebuilder) {
12836 mono_domain_unlock (domain);
12837 mono_loader_unlock ();
12839 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12840 mono_error_raise_exception (&error); /* FIXME don't raise here */
12845 * Fields to set in klass:
12846 * the various flags: delegate/unicode/contextbound etc.
12848 klass->flags = tb->attrs;
12849 klass->has_cctor = 1;
12850 klass->has_finalize = 1;
12851 klass->has_finalize_inited = 1;
12853 mono_class_setup_parent (klass, klass->parent);
12854 /* fool mono_class_setup_supertypes */
12855 klass->supertypes = NULL;
12856 mono_class_setup_supertypes (klass);
12857 mono_class_setup_mono_type (klass);
12860 if (!((MonoDynamicImage*)klass->image)->run) {
12861 if (klass->generic_container) {
12862 /* FIXME: The code below can't handle generic classes */
12863 klass->wastypebuilder = TRUE;
12864 mono_loader_unlock ();
12865 mono_domain_unlock (domain);
12867 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12868 mono_error_raise_exception (&error); /* FIXME don't raise here */
12875 /* enums are done right away */
12876 if (!klass->enumtype)
12877 if (!ensure_runtime_vtable (klass, &error))
12880 if (tb->subtypes) {
12881 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12882 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12883 mono_class_alloc_ext (klass);
12884 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12885 if (!is_ok (&error)) goto failure;
12886 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12890 klass->nested_classes_inited = TRUE;
12892 /* fields and object layout */
12893 if (klass->parent) {
12894 if (!klass->parent->size_inited)
12895 mono_class_init (klass->parent);
12896 klass->instance_size = klass->parent->instance_size;
12897 klass->sizes.class_size = 0;
12898 klass->min_align = klass->parent->min_align;
12899 /* if the type has no fields we won't call the field_setup
12900 * routine which sets up klass->has_references.
12902 klass->has_references |= klass->parent->has_references;
12904 klass->instance_size = sizeof (MonoObject);
12905 klass->min_align = 1;
12908 /* FIXME: handle packing_size and instance_size */
12909 typebuilder_setup_fields (klass, &error);
12910 if (!mono_error_ok (&error))
12912 typebuilder_setup_properties (klass, &error);
12913 if (!mono_error_ok (&error))
12916 typebuilder_setup_events (klass, &error);
12917 if (!mono_error_ok (&error))
12920 klass->wastypebuilder = TRUE;
12923 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12924 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12925 * we want to return normal System.MonoType objects, so clear these out from the cache.
12927 * Together with this we must ensure the contents of all instances to match the created type.
12929 if (domain->type_hash && klass->generic_container)
12930 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12932 mono_domain_unlock (domain);
12933 mono_loader_unlock ();
12935 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12936 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12937 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12940 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12941 mono_error_raise_exception (&error); /* FIXME don't raise here */
12943 g_assert (res != (MonoReflectionType*)tb);
12948 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12949 klass->wastypebuilder = TRUE;
12950 mono_domain_unlock (domain);
12951 mono_loader_unlock ();
12952 mono_error_raise_exception (&error);
12957 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12959 MonoGenericParamFull *param;
12964 image = &gparam->tbuilder->module->dynamic_image->image;
12966 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12968 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12969 g_assert (mono_error_ok (&error));
12970 param->param.num = gparam->index;
12972 if (gparam->mbuilder) {
12973 if (!gparam->mbuilder->generic_container) {
12974 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12975 mono_error_raise_exception (&error); /* FIXME don't raise here */
12977 MonoClass *klass = mono_class_from_mono_type (tb);
12978 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12979 gparam->mbuilder->generic_container->is_method = TRUE;
12981 * Cannot set owner.method, since the MonoMethod is not created yet.
12982 * Set the image field instead, so type_in_image () works.
12984 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12985 gparam->mbuilder->generic_container->owner.image = klass->image;
12987 param->param.owner = gparam->mbuilder->generic_container;
12988 } else if (gparam->tbuilder) {
12989 if (!gparam->tbuilder->generic_container) {
12990 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12991 mono_error_raise_exception (&error); /* FIXME don't raise here */
12992 MonoClass *klass = mono_class_from_mono_type (tb);
12993 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12994 gparam->tbuilder->generic_container->owner.klass = klass;
12996 param->param.owner = gparam->tbuilder->generic_container;
12999 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13001 gparam->type.type = &pklass->byval_arg;
13003 mono_class_set_ref_info (pklass, gparam);
13004 mono_image_append_class_to_reflection_info_set (pklass);
13008 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13011 MonoReflectionModuleBuilder *module = sig->module;
13012 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13013 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13018 check_array_for_usertypes (sig->arguments, &error);
13019 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13021 sigbuffer_init (&buf, 32);
13023 sigbuffer_add_value (&buf, 0x07);
13024 sigbuffer_add_value (&buf, na);
13025 if (assembly != NULL){
13026 for (i = 0; i < na; ++i) {
13027 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13028 encode_reflection_type (assembly, type, &buf, &error);
13029 if (!is_ok (&error)) goto fail;
13033 buflen = buf.p - buf.buf;
13034 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13035 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13036 sigbuffer_free (&buf);
13039 sigbuffer_free (&buf);
13040 mono_error_raise_exception (&error); /* FIXME don't raise here */
13045 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13048 MonoDynamicImage *assembly = sig->module->dynamic_image;
13049 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13054 check_array_for_usertypes (sig->arguments, &error);
13055 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13057 sigbuffer_init (&buf, 32);
13059 sigbuffer_add_value (&buf, 0x06);
13060 for (i = 0; i < na; ++i) {
13061 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13062 encode_reflection_type (assembly, type, &buf, &error);
13063 if (!is_ok (&error))
13067 buflen = buf.p - buf.buf;
13068 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13069 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13070 sigbuffer_free (&buf);
13074 sigbuffer_free (&buf);
13075 mono_error_raise_exception (&error); /* FIXME don't raise here */
13080 MonoMethod *handle;
13081 MonoDomain *domain;
13082 } DynamicMethodReleaseData;
13085 * The runtime automatically clean up those after finalization.
13087 static MonoReferenceQueue *dynamic_method_queue;
13090 free_dynamic_method (void *dynamic_method)
13092 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13093 MonoDomain *domain = data->domain;
13094 MonoMethod *method = data->handle;
13097 mono_domain_lock (domain);
13098 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13099 g_hash_table_remove (domain->method_to_dyn_method, method);
13100 mono_domain_unlock (domain);
13101 g_assert (dis_link);
13102 mono_gchandle_free (dis_link);
13104 mono_runtime_free_method (domain, method);
13109 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13112 MonoReferenceQueue *queue;
13113 MonoMethod *handle;
13114 DynamicMethodReleaseData *release_data;
13115 ReflectionMethodBuilder rmb;
13116 MonoMethodSignature *sig;
13118 MonoDomain *domain;
13122 if (mono_runtime_is_shutting_down ())
13123 mono_raise_exception (mono_get_exception_invalid_operation (""));
13125 if (!(queue = dynamic_method_queue)) {
13126 mono_loader_lock ();
13127 if (!(queue = dynamic_method_queue))
13128 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13129 mono_loader_unlock ();
13132 sig = dynamic_method_to_signature (mb);
13134 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13137 * Resolve references.
13140 * Every second entry in the refs array is reserved for storing handle_class,
13141 * which is needed by the ldtoken implementation in the JIT.
13143 rmb.nrefs = mb->nrefs;
13144 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13145 for (i = 0; i < mb->nrefs; i += 2) {
13146 MonoClass *handle_class;
13148 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13150 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13151 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13153 * The referenced DynamicMethod should already be created by the managed
13154 * code, except in the case of circular references. In that case, we store
13155 * method in the refs array, and fix it up later when the referenced
13156 * DynamicMethod is created.
13158 if (method->mhandle) {
13159 ref = method->mhandle;
13161 /* FIXME: GC object stored in unmanaged memory */
13164 /* FIXME: GC object stored in unmanaged memory */
13165 method->referenced_by = g_slist_append (method->referenced_by, mb);
13167 handle_class = mono_defaults.methodhandle_class;
13169 MonoException *ex = NULL;
13170 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13172 ex = mono_get_exception_type_load (NULL, NULL);
13173 else if (mono_security_core_clr_enabled ())
13174 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13178 mono_raise_exception (ex);
13183 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13184 rmb.refs [i + 1] = handle_class;
13188 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13189 if (!is_ok (&error)) {
13191 mono_error_raise_exception (&error); /* FIXME don't raise here */
13193 klass = mono_class_from_mono_type (owner_type);
13195 klass = mono_defaults.object_class;
13198 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13199 release_data = g_new (DynamicMethodReleaseData, 1);
13200 release_data->handle = handle;
13201 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13202 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13203 g_free (release_data);
13205 /* Fix up refs entries pointing at us */
13206 for (l = mb->referenced_by; l; l = l->next) {
13207 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13208 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13211 g_assert (method->mhandle);
13213 data = (gpointer*)wrapper->method_data;
13214 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13215 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13216 data [i + 1] = mb->mhandle;
13219 g_slist_free (mb->referenced_by);
13223 /* ilgen is no longer needed */
13226 domain = mono_domain_get ();
13227 mono_domain_lock (domain);
13228 if (!domain->method_to_dyn_method)
13229 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13230 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13231 mono_domain_unlock (domain);
13234 #endif /* DISABLE_REFLECTION_EMIT */
13238 * mono_reflection_is_valid_dynamic_token:
13240 * Returns TRUE if token is valid.
13244 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13246 return lookup_dyn_token (image, token) != NULL;
13249 MonoMethodSignature *
13250 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13252 MonoMethodSignature *sig;
13253 g_assert (image_is_dynamic (image));
13255 mono_error_init (error);
13257 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13261 return mono_method_signature_checked (method, error);
13264 #ifndef DISABLE_REFLECTION_EMIT
13267 * mono_reflection_lookup_dynamic_token:
13269 * Finish the Builder object pointed to by TOKEN and return the corresponding
13270 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13271 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13274 * LOCKING: Take the loader lock
13277 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13279 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13283 obj = lookup_dyn_token (assembly, token);
13286 g_error ("Could not find required dynamic token 0x%08x", token);
13292 handle_class = &klass;
13293 return resolve_object (image, obj, handle_class, context);
13297 * ensure_complete_type:
13299 * Ensure that KLASS is completed if it is a dynamic type, or references
13303 ensure_complete_type (MonoClass *klass)
13307 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13308 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13310 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13311 mono_error_raise_exception (&error); /* FIXME don't raise here */
13313 // Asserting here could break a lot of code
13314 //g_assert (klass->wastypebuilder);
13317 if (klass->generic_class) {
13318 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13321 for (i = 0; i < inst->type_argc; ++i) {
13322 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13328 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13331 gpointer result = NULL;
13333 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13334 result = mono_string_intern_checked ((MonoString*)obj, &error);
13335 mono_error_raise_exception (&error); /* FIXME don't raise here */
13336 *handle_class = mono_defaults.string_class;
13338 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13339 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13340 mono_error_raise_exception (&error); /* FIXME don't raise here */
13341 MonoClass *mc = mono_class_from_mono_type (type);
13342 if (!mono_class_init (mc))
13343 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13346 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13347 mono_error_raise_exception (&error); /* FIXME don't raise here */
13349 result = mono_class_from_mono_type (inflated);
13350 mono_metadata_free_type (inflated);
13352 result = mono_class_from_mono_type (type);
13354 *handle_class = mono_defaults.typehandle_class;
13356 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13357 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13358 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13359 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13360 result = ((MonoReflectionMethod*)obj)->method;
13363 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13364 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13366 *handle_class = mono_defaults.methodhandle_class;
13368 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13369 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13370 result = mb->mhandle;
13372 /* Type is not yet created */
13373 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13375 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13376 mono_error_raise_exception (&error); /* FIXME don't raise here */
13379 * Hopefully this has been filled in by calling CreateType() on the
13383 * TODO: This won't work if the application finishes another
13384 * TypeBuilder instance instead of this one.
13386 result = mb->mhandle;
13390 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13391 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13393 *handle_class = mono_defaults.methodhandle_class;
13394 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13395 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13397 result = cb->mhandle;
13399 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13401 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13402 mono_error_raise_exception (&error); /* FIXME don't raise here */
13403 result = cb->mhandle;
13407 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13408 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13410 *handle_class = mono_defaults.methodhandle_class;
13411 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13412 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13414 ensure_complete_type (field->parent);
13416 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13417 mono_error_raise_exception (&error); /* FIXME don't raise here */
13419 MonoClass *klass = mono_class_from_mono_type (inflated);
13420 MonoClassField *inflated_field;
13421 gpointer iter = NULL;
13422 mono_metadata_free_type (inflated);
13423 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13424 if (!strcmp (field->name, inflated_field->name))
13427 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13428 result = inflated_field;
13432 *handle_class = mono_defaults.fieldhandle_class;
13434 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13435 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13436 result = fb->handle;
13439 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13441 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13442 mono_error_raise_exception (&error); /* FIXME don't raise here */
13443 result = fb->handle;
13446 if (fb->handle && fb->handle->parent->generic_container) {
13447 MonoClass *klass = fb->handle->parent;
13448 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13449 mono_error_raise_exception (&error); /* FIXME don't raise here */
13451 MonoClass *inflated = mono_class_from_mono_type (type);
13453 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13455 mono_metadata_free_type (type);
13457 *handle_class = mono_defaults.fieldhandle_class;
13458 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13459 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13460 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13461 mono_error_raise_exception (&error); /* FIXME don't raise here */
13464 klass = type->data.klass;
13465 if (klass->wastypebuilder) {
13466 /* Already created */
13470 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13471 mono_error_raise_exception (&error); /* FIXME don't raise here */
13472 result = type->data.klass;
13475 *handle_class = mono_defaults.typehandle_class;
13476 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13477 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13478 MonoMethodSignature *sig;
13481 if (helper->arguments)
13482 nargs = mono_array_length (helper->arguments);
13486 sig = mono_metadata_signature_alloc (image, nargs);
13487 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13488 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13490 if (helper->unmanaged_call_conv) { /* unmanaged */
13491 sig->call_convention = helper->unmanaged_call_conv - 1;
13492 sig->pinvoke = TRUE;
13493 } else if (helper->call_conv & 0x02) {
13494 sig->call_convention = MONO_CALL_VARARG;
13496 sig->call_convention = MONO_CALL_DEFAULT;
13499 sig->param_count = nargs;
13500 /* TODO: Copy type ? */
13501 sig->ret = helper->return_type->type;
13502 for (i = 0; i < nargs; ++i) {
13503 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13504 mono_error_raise_exception (&error); /* FIXME don't raise here */
13508 *handle_class = NULL;
13509 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13510 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13511 /* Already created by the managed code */
13512 g_assert (method->mhandle);
13513 result = method->mhandle;
13514 *handle_class = mono_defaults.methodhandle_class;
13515 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13516 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13517 mono_error_raise_exception (&error); /* FIXME don't raise here */
13518 type = mono_class_inflate_generic_type_checked (type, context, &error);
13519 mono_error_raise_exception (&error); /* FIXME don't raise here */
13521 result = mono_class_from_mono_type (type);
13522 *handle_class = mono_defaults.typehandle_class;
13524 mono_metadata_free_type (type);
13525 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13526 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13527 mono_error_raise_exception (&error); /* FIXME don't raise here */
13528 type = mono_class_inflate_generic_type_checked (type, context, &error);
13529 mono_error_raise_exception (&error); /* FIXME don't raise here */
13531 result = mono_class_from_mono_type (type);
13532 *handle_class = mono_defaults.typehandle_class;
13534 mono_metadata_free_type (type);
13535 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13536 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13537 MonoClass *inflated;
13539 MonoClassField *field;
13541 if (is_sre_field_builder (mono_object_class (f->fb)))
13542 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13543 else if (is_sr_mono_field (mono_object_class (f->fb)))
13544 field = ((MonoReflectionField*)f->fb)->field;
13546 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)));
13548 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13549 mono_error_raise_exception (&error); /* FIXME don't raise here */
13550 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13551 mono_error_raise_exception (&error); /* FIXME don't raise here */
13553 inflated = mono_class_from_mono_type (type);
13555 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13556 ensure_complete_type (field->parent);
13558 mono_metadata_free_type (type);
13559 *handle_class = mono_defaults.fieldhandle_class;
13560 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13561 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13562 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13563 mono_error_raise_exception (&error); /* FIXME don't raise here */
13564 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13565 mono_error_raise_exception (&error); /* FIXME don't raise here */
13567 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13568 MonoMethod *method;
13570 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13571 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13572 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13573 method = ((MonoReflectionMethod *)c->cb)->method;
13575 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)));
13577 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13578 *handle_class = mono_defaults.methodhandle_class;
13579 mono_metadata_free_type (type);
13580 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13581 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13582 if (m->method_args) {
13583 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13584 mono_error_raise_exception (&error); /* FIXME don't raise here */
13586 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13587 mono_error_assert_ok (&error);
13590 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13591 mono_error_raise_exception (&error); /* FIXME don't raise here */
13592 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13593 mono_error_raise_exception (&error); /* FIXME don't raise here */
13595 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13596 MonoMethod *method;
13598 if (is_sre_method_builder (mono_object_class (m->mb)))
13599 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13600 else if (is_sr_mono_method (mono_object_class (m->mb)))
13601 method = ((MonoReflectionMethod *)m->mb)->method;
13603 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)));
13605 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13606 mono_metadata_free_type (type);
13608 *handle_class = mono_defaults.methodhandle_class;
13609 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13610 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13613 MonoMethod *method;
13617 mtype = mono_reflection_type_get_handle (m->parent, &error);
13618 mono_error_raise_exception (&error); /* FIXME don't raise here */
13619 klass = mono_class_from_mono_type (mtype);
13621 /* Find the method */
13623 name = mono_string_to_utf8 (m->name);
13625 while ((method = mono_class_get_methods (klass, &iter))) {
13626 if (!strcmp (method->name, name))
13633 // FIXME: Check parameters/return value etc. match
13636 *handle_class = mono_defaults.methodhandle_class;
13637 } else if (is_sre_array (mono_object_get_class(obj)) ||
13638 is_sre_byref (mono_object_get_class(obj)) ||
13639 is_sre_pointer (mono_object_get_class(obj))) {
13640 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13641 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13642 mono_error_raise_exception (&error); /* FIXME don't raise here */
13645 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13646 mono_error_raise_exception (&error); /* FIXME don't raise here */
13648 result = mono_class_from_mono_type (inflated);
13649 mono_metadata_free_type (inflated);
13651 result = mono_class_from_mono_type (type);
13653 *handle_class = mono_defaults.typehandle_class;
13655 g_print ("%s\n", obj->vtable->klass->name);
13656 g_assert_not_reached ();
13661 #else /* DISABLE_REFLECTION_EMIT */
13664 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13666 g_assert_not_reached ();
13671 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13673 g_assert_not_reached ();
13677 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13679 g_assert_not_reached ();
13683 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13685 g_assert_not_reached ();
13689 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13691 g_assert_not_reached ();
13695 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13697 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13701 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13703 g_assert_not_reached ();
13707 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13709 g_assert_not_reached ();
13712 MonoReflectionModule *
13713 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13715 g_assert_not_reached ();
13720 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13722 g_assert_not_reached ();
13727 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13729 g_assert_not_reached ();
13734 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13735 gboolean create_open_instance, gboolean register_token, MonoError *error)
13737 g_assert_not_reached ();
13742 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13747 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13749 g_assert_not_reached ();
13753 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13756 *num_overrides = 0;
13759 MonoReflectionEvent *
13760 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13762 g_assert_not_reached ();
13766 MonoReflectionType*
13767 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13769 g_assert_not_reached ();
13774 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13776 g_assert_not_reached ();
13780 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13782 g_assert_not_reached ();
13787 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13789 g_assert_not_reached ();
13794 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13799 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13805 mono_reflection_type_get_handle (MonoReflectionType* ref)
13813 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13815 g_assert_not_reached ();
13818 #endif /* DISABLE_REFLECTION_EMIT */
13820 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13821 const static guint32 declsec_flags_map[] = {
13822 0x00000000, /* empty */
13823 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13824 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13825 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13826 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13827 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13828 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13829 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13830 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13831 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13832 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13833 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13834 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13835 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13836 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13837 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13838 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13839 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13840 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13844 * Returns flags that includes all available security action associated to the handle.
13845 * @token: metadata token (either for a class or a method)
13846 * @image: image where resides the metadata.
13849 mono_declsec_get_flags (MonoImage *image, guint32 token)
13851 int index = mono_metadata_declsec_from_index (image, token);
13852 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13853 guint32 result = 0;
13857 /* HasSecurity can be present for other, not specially encoded, attributes,
13858 e.g. SuppressUnmanagedCodeSecurityAttribute */
13862 for (i = index; i < t->rows; i++) {
13863 guint32 cols [MONO_DECL_SECURITY_SIZE];
13865 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13866 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13869 action = cols [MONO_DECL_SECURITY_ACTION];
13870 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13871 result |= declsec_flags_map [action];
13873 g_assert_not_reached ();
13880 * Get the security actions (in the form of flags) associated with the specified method.
13882 * @method: The method for which we want the declarative security flags.
13883 * Return the declarative security flags for the method (only).
13885 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13886 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13889 mono_declsec_flags_from_method (MonoMethod *method)
13891 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13892 /* FIXME: No cache (for the moment) */
13893 guint32 idx = mono_method_get_index (method);
13894 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13895 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13896 return mono_declsec_get_flags (method->klass->image, idx);
13902 * Get the security actions (in the form of flags) associated with the specified class.
13904 * @klass: The class for which we want the declarative security flags.
13905 * Return the declarative security flags for the class.
13907 * Note: We cache the flags inside the MonoClass structure as this will get
13908 * called very often (at least for each method).
13911 mono_declsec_flags_from_class (MonoClass *klass)
13913 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13914 if (!klass->ext || !klass->ext->declsec_flags) {
13917 idx = mono_metadata_token_index (klass->type_token);
13918 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13919 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13920 mono_loader_lock ();
13921 mono_class_alloc_ext (klass);
13922 mono_loader_unlock ();
13923 /* we cache the flags on classes */
13924 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13926 return klass->ext->declsec_flags;
13932 * Get the security actions (in the form of flags) associated with the specified assembly.
13934 * @assembly: The assembly for which we want the declarative security flags.
13935 * Return the declarative security flags for the assembly.
13938 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13940 guint32 idx = 1; /* there is only one assembly */
13941 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13942 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13943 return mono_declsec_get_flags (assembly->image, idx);
13948 * Fill actions for the specific index (which may either be an encoded class token or
13949 * an encoded method token) from the metadata image.
13950 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13953 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13954 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13956 MonoBoolean result = FALSE;
13958 guint32 cols [MONO_DECL_SECURITY_SIZE];
13959 int index = mono_metadata_declsec_from_index (image, token);
13962 t = &image->tables [MONO_TABLE_DECLSECURITY];
13963 for (i = index; i < t->rows; i++) {
13964 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13966 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13969 /* if present only replace (class) permissions with method permissions */
13970 /* if empty accept either class or method permissions */
13971 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13972 if (!actions->demand.blob) {
13973 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13974 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13975 actions->demand.blob = (char*) (blob + 2);
13976 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13979 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13980 if (!actions->noncasdemand.blob) {
13981 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13982 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13983 actions->noncasdemand.blob = (char*) (blob + 2);
13984 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13987 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13988 if (!actions->demandchoice.blob) {
13989 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13990 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13991 actions->demandchoice.blob = (char*) (blob + 2);
13992 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14002 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14003 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14005 guint32 idx = mono_metadata_token_index (klass->type_token);
14006 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14007 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14008 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14012 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14013 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14015 guint32 idx = mono_method_get_index (method);
14016 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14017 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14018 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14022 * Collect all actions (that requires to generate code in mini) assigned for
14023 * the specified method.
14024 * Note: Don't use the content of actions if the function return FALSE.
14027 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14029 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14030 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14031 MonoBoolean result = FALSE;
14034 /* quick exit if no declarative security is present in the metadata */
14035 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14038 /* we want the original as the wrapper is "free" of the security informations */
14039 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14040 method = mono_marshal_method_from_wrapper (method);
14045 /* First we look for method-level attributes */
14046 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14047 mono_class_init (method->klass);
14048 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14050 result = mono_declsec_get_method_demands_params (method, demands,
14051 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14054 /* Here we use (or create) the class declarative cache to look for demands */
14055 flags = mono_declsec_flags_from_class (method->klass);
14056 if (flags & mask) {
14058 mono_class_init (method->klass);
14059 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14061 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14062 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14065 /* The boolean return value is used as a shortcut in case nothing needs to
14066 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14072 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14074 * Note: Don't use the content of actions if the function return FALSE.
14077 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14079 MonoBoolean result = FALSE;
14082 /* quick exit if no declarative security is present in the metadata */
14083 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14086 /* we want the original as the wrapper is "free" of the security informations */
14087 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14088 method = mono_marshal_method_from_wrapper (method);
14093 /* results are independant - zeroize both */
14094 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14095 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14097 /* First we look for method-level attributes */
14098 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14099 mono_class_init (method->klass);
14101 result = mono_declsec_get_method_demands_params (method, cmethod,
14102 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14105 /* Here we use (or create) the class declarative cache to look for demands */
14106 flags = mono_declsec_flags_from_class (method->klass);
14107 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14108 mono_class_init (method->klass);
14110 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14111 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14118 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14120 * @klass The inherited class - this is the class that provides the security check (attributes)
14122 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14124 * Note: Don't use the content of actions if the function return FALSE.
14127 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14129 MonoBoolean result = FALSE;
14132 /* quick exit if no declarative security is present in the metadata */
14133 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14136 /* Here we use (or create) the class declarative cache to look for demands */
14137 flags = mono_declsec_flags_from_class (klass);
14138 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14139 mono_class_init (klass);
14140 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14142 result |= mono_declsec_get_class_demands_params (klass, demands,
14143 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14150 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14152 * Note: Don't use the content of actions if the function return FALSE.
14155 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14157 /* quick exit if no declarative security is present in the metadata */
14158 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14161 /* we want the original as the wrapper is "free" of the security informations */
14162 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14163 method = mono_marshal_method_from_wrapper (method);
14168 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14169 mono_class_init (method->klass);
14170 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14172 return mono_declsec_get_method_demands_params (method, demands,
14173 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14180 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14182 guint32 cols [MONO_DECL_SECURITY_SIZE];
14186 int index = mono_metadata_declsec_from_index (image, token);
14190 t = &image->tables [MONO_TABLE_DECLSECURITY];
14191 for (i = index; i < t->rows; i++) {
14192 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14194 /* shortcut - index are ordered */
14195 if (token != cols [MONO_DECL_SECURITY_PARENT])
14198 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14199 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14200 entry->blob = (char*) (metadata + 2);
14201 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14210 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14212 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14213 guint32 idx = mono_method_get_index (method);
14214 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14215 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14216 return get_declsec_action (method->klass->image, idx, action, entry);
14222 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14225 guint32 flags = mono_declsec_flags_from_class (klass);
14226 if (declsec_flags_map [action] & flags) {
14227 guint32 idx = mono_metadata_token_index (klass->type_token);
14228 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14229 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14230 return get_declsec_action (klass->image, idx, action, entry);
14236 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14238 guint32 idx = 1; /* there is only one assembly */
14239 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14240 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14242 return get_declsec_action (assembly->image, idx, action, entry);
14246 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14249 MonoObject *res, *exc;
14251 static MonoMethod *method = NULL;
14253 if (method == NULL) {
14254 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14259 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14260 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14262 g_assert (mono_class_get_ref_info (klass));
14263 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14265 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14266 mono_error_raise_exception (&error); /* FIXME don't raise here */
14268 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14270 if (exc || !mono_error_ok (&error)) {
14271 mono_error_cleanup (&error);
14274 return *(MonoBoolean*)mono_object_unbox (res);
14278 * mono_reflection_type_get_type:
14279 * @reftype: the System.Type object
14281 * Returns the MonoType* associated with the C# System.Type object @reftype.
14284 mono_reflection_type_get_type (MonoReflectionType *reftype)
14286 g_assert (reftype);
14289 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14290 mono_error_assert_ok (&error);
14295 * mono_reflection_assembly_get_assembly:
14296 * @refassembly: the System.Reflection.Assembly object
14298 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14301 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14303 g_assert (refassembly);
14305 return refassembly->assembly;