2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
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 gboolean type_is_reference (MonoType *type);
192 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
193 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
194 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
196 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
197 static void init_type_builder_generics (MonoObject *type);
199 #define RESOLVE_TYPE(type, error) do { \
200 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
202 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
203 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
204 __type = mono_reflection_type_resolve_user_types (__type, error); \
205 if (mono_error_ok (error)) \
206 mono_array_set (arr, MonoReflectionType*, index, __type); \
209 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
211 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
212 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
214 #if SIZEOF_VOID_P == 4
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
217 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
220 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
221 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
223 /* Class lazy loading functions */
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
234 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
235 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
236 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
237 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
238 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
241 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
242 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
244 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
245 static GPtrArray *dynamic_images;
246 static mono_mutex_t dynamic_images_mutex;
249 dynamic_images_lock (void)
251 mono_os_mutex_lock (&dynamic_images_mutex);
255 dynamic_images_unlock (void)
257 mono_os_mutex_unlock (&dynamic_images_mutex);
261 * mono_find_dynamic_image_owner:
263 * Find the dynamic image, if any, which a given pointer is located in the memory of.
266 mono_find_dynamic_image_owner (void *ptr)
268 MonoImage *owner = NULL;
271 dynamic_images_lock ();
275 for (i = 0; !owner && i < dynamic_images->len; ++i) {
276 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
277 if (mono_mempool_contains_addr (image->mempool, ptr))
282 dynamic_images_unlock ();
288 mono_reflection_init (void)
290 mono_os_mutex_init (&dynamic_images_mutex);
294 dynamic_image_lock (MonoDynamicImage *image)
296 MONO_PREPARE_BLOCKING;
297 mono_image_lock ((MonoImage*)image);
298 MONO_FINISH_BLOCKING;
302 dynamic_image_unlock (MonoDynamicImage *image)
304 mono_image_unlock ((MonoImage*)image);
308 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
310 MONO_REQ_GC_UNSAFE_MODE;
312 dynamic_image_lock (assembly);
313 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
314 dynamic_image_unlock (assembly);
318 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
320 MONO_REQ_GC_UNSAFE_MODE;
324 dynamic_image_lock (assembly);
325 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
326 dynamic_image_unlock (assembly);
332 sigbuffer_init (SigBuffer *buf, int size)
334 MONO_REQ_GC_NEUTRAL_MODE;
336 buf->buf = (char *)g_malloc (size);
338 buf->end = buf->buf + size;
342 sigbuffer_make_room (SigBuffer *buf, int size)
344 MONO_REQ_GC_NEUTRAL_MODE;
346 if (buf->end - buf->p < size) {
347 int new_size = buf->end - buf->buf + size + 32;
348 char *p = (char *)g_realloc (buf->buf, new_size);
349 size = buf->p - buf->buf;
352 buf->end = buf->buf + new_size;
357 sigbuffer_add_value (SigBuffer *buf, guint32 val)
359 MONO_REQ_GC_NEUTRAL_MODE;
361 sigbuffer_make_room (buf, 6);
362 mono_metadata_encode_value (val, buf->p, &buf->p);
366 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
368 MONO_REQ_GC_NEUTRAL_MODE;
370 sigbuffer_make_room (buf, 1);
376 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
378 MONO_REQ_GC_NEUTRAL_MODE;
380 sigbuffer_make_room (buf, size);
381 memcpy (buf->p, p, size);
386 sigbuffer_free (SigBuffer *buf)
388 MONO_REQ_GC_NEUTRAL_MODE;
393 #ifndef DISABLE_REFLECTION_EMIT
397 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
401 image_g_malloc (MonoImage *image, guint size)
403 MONO_REQ_GC_NEUTRAL_MODE;
406 return mono_image_alloc (image, size);
408 return g_malloc (size);
410 #endif /* !DISABLE_REFLECTION_EMIT */
415 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
419 image_g_malloc0 (MonoImage *image, guint size)
421 MONO_REQ_GC_NEUTRAL_MODE;
424 return mono_image_alloc0 (image, size);
426 return g_malloc0 (size);
431 * @image: a MonoImage
434 * If @image is NULL, free @ptr, otherwise do nothing.
437 image_g_free (MonoImage *image, gpointer ptr)
443 #ifndef DISABLE_REFLECTION_EMIT
445 image_strdup (MonoImage *image, const char *s)
447 MONO_REQ_GC_NEUTRAL_MODE;
450 return mono_image_strdup (image, s);
456 #define image_g_new(image,struct_type, n_structs) \
457 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459 #define image_g_new0(image,struct_type, n_structs) \
460 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
464 alloc_table (MonoDynamicTable *table, guint nrows)
466 MONO_REQ_GC_NEUTRAL_MODE;
469 g_assert (table->columns);
470 if (nrows + 1 >= table->alloc_rows) {
471 while (nrows + 1 >= table->alloc_rows) {
472 if (table->alloc_rows == 0)
473 table->alloc_rows = 16;
475 table->alloc_rows *= 2;
478 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
483 make_room_in_stream (MonoDynamicStream *stream, int size)
485 MONO_REQ_GC_NEUTRAL_MODE;
487 if (size <= stream->alloc_size)
490 while (stream->alloc_size <= size) {
491 if (stream->alloc_size < 4096)
492 stream->alloc_size = 4096;
494 stream->alloc_size *= 2;
497 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
501 string_heap_insert (MonoDynamicStream *sh, const char *str)
503 MONO_REQ_GC_NEUTRAL_MODE;
507 gpointer oldkey, oldval;
509 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
510 return GPOINTER_TO_UINT (oldval);
512 len = strlen (str) + 1;
515 make_room_in_stream (sh, idx + len);
518 * We strdup the string even if we already copy them in sh->data
519 * so that the string pointers in the hash remain valid even if
520 * we need to realloc sh->data. We may want to avoid that later.
522 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
523 memcpy (sh->data + idx, str, len);
529 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
531 MONO_REQ_GC_UNSAFE_MODE;
533 char *name = mono_string_to_utf8 (str);
535 idx = string_heap_insert (sh, name);
540 #ifndef DISABLE_REFLECTION_EMIT
542 string_heap_init (MonoDynamicStream *sh)
544 MONO_REQ_GC_NEUTRAL_MODE;
547 sh->alloc_size = 4096;
548 sh->data = (char *)g_malloc (4096);
549 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
550 string_heap_insert (sh, "");
555 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
557 MONO_REQ_GC_NEUTRAL_MODE;
561 make_room_in_stream (stream, stream->index + len);
562 memcpy (stream->data + stream->index, data, len);
564 stream->index += len;
566 * align index? Not without adding an additional param that controls it since
567 * we may store a blob value in pieces.
573 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
575 MONO_REQ_GC_NEUTRAL_MODE;
579 make_room_in_stream (stream, stream->index + len);
580 memset (stream->data + stream->index, 0, len);
582 stream->index += len;
587 stream_data_align (MonoDynamicStream *stream)
589 MONO_REQ_GC_NEUTRAL_MODE;
592 guint32 count = stream->index % 4;
594 /* we assume the stream data will be aligned */
596 mono_image_add_stream_data (stream, buf, 4 - count);
599 #ifndef DISABLE_REFLECTION_EMIT
601 mono_blob_entry_hash (const char* str)
603 MONO_REQ_GC_NEUTRAL_MODE;
607 len = mono_metadata_decode_blob_size (str, &str);
611 for (str += 1; str < end; str++)
612 h = (h << 5) - h + *str;
620 mono_blob_entry_equal (const char *str1, const char *str2) {
621 MONO_REQ_GC_NEUTRAL_MODE;
626 len = mono_metadata_decode_blob_size (str1, &end1);
627 len2 = mono_metadata_decode_blob_size (str2, &end2);
630 return memcmp (end1, end2, len) == 0;
634 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
636 MONO_REQ_GC_NEUTRAL_MODE;
640 gpointer oldkey, oldval;
642 copy = (char *)g_malloc (s1+s2);
643 memcpy (copy, b1, s1);
644 memcpy (copy + s1, b2, s2);
645 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
647 idx = GPOINTER_TO_UINT (oldval);
649 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
650 mono_image_add_stream_data (&assembly->blob, b2, s2);
651 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
657 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
659 MONO_REQ_GC_NEUTRAL_MODE;
663 guint32 size = buf->p - buf->buf;
665 g_assert (size <= (buf->end - buf->buf));
666 mono_metadata_encode_value (size, b, &b);
667 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
671 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
672 * dest may be misaligned.
675 swap_with_size (char *dest, const char* val, int len, int nelem) {
676 MONO_REQ_GC_NEUTRAL_MODE;
677 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
680 for (elem = 0; elem < nelem; ++elem) {
706 g_assert_not_reached ();
712 memcpy (dest, val, len * nelem);
717 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
719 MONO_REQ_GC_UNSAFE_MODE;
723 guint32 idx = 0, len;
725 len = str->length * 2;
726 mono_metadata_encode_value (len, b, &b);
727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
729 char *swapped = g_malloc (2 * mono_string_length (str));
730 const char *p = (const char*)mono_string_chars (str);
732 swap_with_size (swapped, p, 2, mono_string_length (str));
733 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
737 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
742 #ifndef DISABLE_REFLECTION_EMIT
744 default_class_from_mono_type (MonoType *type)
746 MONO_REQ_GC_NEUTRAL_MODE;
748 switch (type->type) {
749 case MONO_TYPE_OBJECT:
750 return mono_defaults.object_class;
752 return mono_defaults.void_class;
753 case MONO_TYPE_BOOLEAN:
754 return mono_defaults.boolean_class;
756 return mono_defaults.char_class;
758 return mono_defaults.sbyte_class;
760 return mono_defaults.byte_class;
762 return mono_defaults.int16_class;
764 return mono_defaults.uint16_class;
766 return mono_defaults.int32_class;
768 return mono_defaults.uint32_class;
770 return mono_defaults.int_class;
772 return mono_defaults.uint_class;
774 return mono_defaults.int64_class;
776 return mono_defaults.uint64_class;
778 return mono_defaults.single_class;
780 return mono_defaults.double_class;
781 case MONO_TYPE_STRING:
782 return mono_defaults.string_class;
784 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
785 g_assert_not_reached ();
793 * mono_class_get_ref_info:
795 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
798 mono_class_get_ref_info (MonoClass *klass)
800 MONO_REQ_GC_UNSAFE_MODE;
802 if (klass->ref_info_handle == 0)
805 return mono_gchandle_get_target (klass->ref_info_handle);
809 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
811 MONO_REQ_GC_UNSAFE_MODE;
813 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
814 g_assert (klass->ref_info_handle != 0);
818 mono_class_free_ref_info (MonoClass *klass)
820 MONO_REQ_GC_NEUTRAL_MODE;
822 if (klass->ref_info_handle) {
823 mono_gchandle_free (klass->ref_info_handle);
824 klass->ref_info_handle = 0;
829 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
831 MONO_REQ_GC_NEUTRAL_MODE;
834 MonoGenericInst *class_inst;
839 class_inst = gclass->context.class_inst;
841 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
842 klass = gclass->container_class;
843 sigbuffer_add_value (buf, klass->byval_arg.type);
844 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
846 sigbuffer_add_value (buf, class_inst->type_argc);
847 for (i = 0; i < class_inst->type_argc; ++i)
848 encode_type (assembly, class_inst->type_argv [i], buf);
853 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
855 MONO_REQ_GC_NEUTRAL_MODE;
858 g_assert_not_reached ();
863 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
867 case MONO_TYPE_BOOLEAN:
881 case MONO_TYPE_STRING:
882 case MONO_TYPE_OBJECT:
883 case MONO_TYPE_TYPEDBYREF:
884 sigbuffer_add_value (buf, type->type);
887 sigbuffer_add_value (buf, type->type);
888 encode_type (assembly, type->data.type, buf);
890 case MONO_TYPE_SZARRAY:
891 sigbuffer_add_value (buf, type->type);
892 encode_type (assembly, &type->data.klass->byval_arg, buf);
894 case MONO_TYPE_VALUETYPE:
895 case MONO_TYPE_CLASS: {
896 MonoClass *k = mono_class_from_mono_type (type);
898 if (k->generic_container) {
899 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
900 encode_generic_class (assembly, gclass, buf);
903 * Make sure we use the correct type.
905 sigbuffer_add_value (buf, k->byval_arg.type);
907 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
908 * otherwise two typerefs could point to the same type, leading to
909 * verification errors.
911 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
915 case MONO_TYPE_ARRAY:
916 sigbuffer_add_value (buf, type->type);
917 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
918 sigbuffer_add_value (buf, type->data.array->rank);
919 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
920 sigbuffer_add_value (buf, 0);
922 case MONO_TYPE_GENERICINST:
923 encode_generic_class (assembly, type->data.generic_class, buf);
927 sigbuffer_add_value (buf, type->type);
928 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
931 g_error ("need to encode type %x", type->type);
936 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
938 MONO_REQ_GC_UNSAFE_MODE;
940 mono_error_init (error);
943 sigbuffer_add_value (buf, MONO_TYPE_VOID);
947 MonoType *t = mono_reflection_type_get_handle (type, error);
948 return_if_nok (error);
949 encode_type (assembly, t, buf);
953 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
955 MONO_REQ_GC_UNSAFE_MODE;
959 mono_error_init (error);
962 for (i = 0; i < mono_array_length (modreq); ++i) {
963 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
964 return_if_nok (error);
965 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
966 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
970 for (i = 0; i < mono_array_length (modopt); ++i) {
971 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
972 return_if_nok (error);
973 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
974 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
979 #ifndef DISABLE_REFLECTION_EMIT
981 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
983 MONO_REQ_GC_UNSAFE_MODE;
987 guint32 nparams = sig->param_count;
993 sigbuffer_init (&buf, 32);
995 * FIXME: vararg, explicit_this, differenc call_conv values...
997 idx = sig->call_convention;
999 idx |= 0x20; /* hasthis */
1000 if (sig->generic_param_count)
1001 idx |= 0x10; /* generic */
1002 sigbuffer_add_byte (&buf, idx);
1003 if (sig->generic_param_count)
1004 sigbuffer_add_value (&buf, sig->generic_param_count);
1005 sigbuffer_add_value (&buf, nparams);
1006 encode_type (assembly, sig->ret, &buf);
1007 for (i = 0; i < nparams; ++i) {
1008 if (i == sig->sentinelpos)
1009 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1010 encode_type (assembly, sig->params [i], &buf);
1012 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1013 sigbuffer_free (&buf);
1019 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1021 MONO_REQ_GC_UNSAFE_MODE;
1023 mono_error_init (error);
1026 * FIXME: reuse code from method_encode_signature().
1030 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1031 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1032 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1035 sigbuffer_init (&buf, 32);
1036 /* LAMESPEC: all the call conv spec is foobared */
1037 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1038 if (mb->call_conv & 2)
1039 idx |= 0x5; /* vararg */
1040 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1041 idx |= 0x20; /* hasthis */
1043 idx |= 0x10; /* generic */
1044 sigbuffer_add_byte (&buf, idx);
1046 sigbuffer_add_value (&buf, ngparams);
1047 sigbuffer_add_value (&buf, nparams + notypes);
1048 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1051 encode_reflection_type (assembly, mb->rtype, &buf, error);
1054 for (i = 0; i < nparams; ++i) {
1055 MonoArray *modreq = NULL;
1056 MonoArray *modopt = NULL;
1057 MonoReflectionType *pt;
1059 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1060 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1061 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1062 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1063 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1066 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1067 encode_reflection_type (assembly, pt, &buf, error);
1072 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1073 for (i = 0; i < notypes; ++i) {
1074 MonoReflectionType *pt;
1076 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1077 encode_reflection_type (assembly, pt, &buf, error);
1082 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1084 sigbuffer_free (&buf);
1089 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1091 MONO_REQ_GC_UNSAFE_MODE;
1093 mono_error_init (error);
1095 MonoDynamicTable *table;
1097 guint32 idx, sig_idx;
1098 guint nl = mono_array_length (ilgen->locals);
1102 sigbuffer_init (&buf, 32);
1103 sigbuffer_add_value (&buf, 0x07);
1104 sigbuffer_add_value (&buf, nl);
1105 for (i = 0; i < nl; ++i) {
1106 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1109 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1111 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1112 if (!is_ok (error)) {
1113 sigbuffer_free (&buf);
1117 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1118 sigbuffer_free (&buf);
1120 if (assembly->standalonesig_cache == NULL)
1121 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1122 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1126 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1127 idx = table->next_idx ++;
1129 alloc_table (table, table->rows);
1130 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1132 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1134 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1140 method_count_clauses (MonoReflectionILGen *ilgen)
1142 MONO_REQ_GC_UNSAFE_MODE;
1144 guint32 num_clauses = 0;
1147 MonoILExceptionInfo *ex_info;
1148 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1149 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1150 if (ex_info->handlers)
1151 num_clauses += mono_array_length (ex_info->handlers);
1159 #ifndef DISABLE_REFLECTION_EMIT
1160 static MonoExceptionClause*
1161 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1163 MONO_REQ_GC_UNSAFE_MODE;
1165 mono_error_init (error);
1167 MonoExceptionClause *clauses;
1168 MonoExceptionClause *clause;
1169 MonoILExceptionInfo *ex_info;
1170 MonoILExceptionBlock *ex_block;
1171 guint32 finally_start;
1172 int i, j, clause_index;;
1174 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1177 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1178 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1179 finally_start = ex_info->start + ex_info->len;
1180 if (!ex_info->handlers)
1182 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1183 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1184 clause = &(clauses [clause_index]);
1186 clause->flags = ex_block->type;
1187 clause->try_offset = ex_info->start;
1189 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1190 clause->try_len = finally_start - ex_info->start;
1192 clause->try_len = ex_info->len;
1193 clause->handler_offset = ex_block->start;
1194 clause->handler_len = ex_block->len;
1195 if (ex_block->extype) {
1196 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1198 if (!is_ok (error)) {
1199 image_g_free (image, clauses);
1202 clause->data.catch_class = mono_class_from_mono_type (extype);
1204 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1205 clause->data.filter_offset = ex_block->filter_offset;
1207 clause->data.filter_offset = 0;
1209 finally_start = ex_block->start + ex_block->len;
1217 #endif /* !DISABLE_REFLECTION_EMIT */
1220 * method_encode_code:
1222 * @assembly the assembly
1223 * @mb the managed MethodBuilder
1224 * @error set on error
1226 * Note that the return value is not sensible if @error is set.
1229 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1231 MONO_REQ_GC_UNSAFE_MODE;
1236 gint32 max_stack, i;
1237 gint32 num_locals = 0;
1238 gint32 num_exception = 0;
1241 char fat_header [12];
1243 guint16 short_value;
1244 guint32 local_sig = 0;
1245 guint32 header_size = 12;
1248 mono_error_init (error);
1250 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1251 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1255 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1257 code = mb->ilgen->code;
1258 code_size = mb->ilgen->code_len;
1259 max_stack = mb->ilgen->max_stack;
1260 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1261 if (mb->ilgen->ex_handlers)
1262 num_exception = method_count_clauses (mb->ilgen);
1266 char *name = mono_string_to_utf8 (mb->name);
1267 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1268 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1274 code_size = mono_array_length (code);
1275 max_stack = 8; /* we probably need to run a verifier on the code... */
1278 stream_data_align (&assembly->code);
1280 /* check for exceptions, maxstack, locals */
1281 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1283 if (code_size < 64 && !(code_size & 1)) {
1284 flags = (code_size << 2) | 0x2;
1285 } else if (code_size < 32 && (code_size & 1)) {
1286 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1290 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1291 /* add to the fixup todo list */
1292 if (mb->ilgen && mb->ilgen->num_token_fixups)
1293 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1294 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1295 return assembly->text_rva + idx;
1299 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1300 return_val_if_nok (error, 0);
1303 * FIXME: need to set also the header size in fat_flags.
1304 * (and more sects and init locals flags)
1308 fat_flags |= METHOD_HEADER_MORE_SECTS;
1309 if (mb->init_locals)
1310 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1311 fat_header [0] = fat_flags;
1312 fat_header [1] = (header_size / 4 ) << 4;
1313 short_value = GUINT16_TO_LE (max_stack);
1314 memcpy (fat_header + 2, &short_value, 2);
1315 int_value = GUINT32_TO_LE (code_size);
1316 memcpy (fat_header + 4, &int_value, 4);
1317 int_value = GUINT32_TO_LE (local_sig);
1318 memcpy (fat_header + 8, &int_value, 4);
1319 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1320 /* add to the fixup todo list */
1321 if (mb->ilgen && mb->ilgen->num_token_fixups)
1322 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1324 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1325 if (num_exception) {
1326 unsigned char sheader [4];
1327 MonoILExceptionInfo * ex_info;
1328 MonoILExceptionBlock * ex_block;
1331 stream_data_align (&assembly->code);
1332 /* always use fat format for now */
1333 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1334 num_exception *= 6 * sizeof (guint32);
1335 num_exception += 4; /* include the size of the header */
1336 sheader [1] = num_exception & 0xff;
1337 sheader [2] = (num_exception >> 8) & 0xff;
1338 sheader [3] = (num_exception >> 16) & 0xff;
1339 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1340 /* fat header, so we are already aligned */
1342 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1343 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1344 if (ex_info->handlers) {
1345 int finally_start = ex_info->start + ex_info->len;
1346 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1348 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1350 val = GUINT32_TO_LE (ex_block->type);
1351 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353 val = GUINT32_TO_LE (ex_info->start);
1354 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1355 /* need fault, too, probably */
1356 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1357 val = GUINT32_TO_LE (finally_start - ex_info->start);
1359 val = GUINT32_TO_LE (ex_info->len);
1360 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1361 /* handler offset */
1362 val = GUINT32_TO_LE (ex_block->start);
1363 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365 val = GUINT32_TO_LE (ex_block->len);
1366 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1367 finally_start = ex_block->start + ex_block->len;
1368 if (ex_block->extype) {
1369 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1370 return_val_if_nok (error, 0);
1372 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1374 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1375 val = ex_block->filter_offset;
1379 val = GUINT32_TO_LE (val);
1380 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1381 /*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",
1382 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);*/
1385 g_error ("No clauses for ex info block %d", i);
1389 return assembly->text_rva + idx;
1393 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1395 MONO_REQ_GC_NEUTRAL_MODE;
1398 MonoDynamicTable *table;
1401 table = &assembly->tables [table_idx];
1403 g_assert (col < table->columns);
1405 values = table->values + table->columns;
1406 for (i = 1; i <= table->rows; ++i) {
1407 if (values [col] == token)
1409 values += table->columns;
1415 * LOCKING: Acquires the loader lock.
1417 static MonoCustomAttrInfo*
1418 lookup_custom_attr (MonoImage *image, gpointer member)
1420 MONO_REQ_GC_NEUTRAL_MODE;
1422 MonoCustomAttrInfo* res;
1424 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1429 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1435 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1437 MONO_REQ_GC_UNSAFE_MODE;
1439 /* FIXME: Need to do more checks */
1440 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1441 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1443 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1450 static MonoCustomAttrInfo*
1451 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1453 MONO_REQ_GC_UNSAFE_MODE;
1455 int i, index, count, not_visible;
1456 MonoCustomAttrInfo *ainfo;
1457 MonoReflectionCustomAttr *cattr;
1461 /* FIXME: check in assembly the Run flag is set */
1463 count = mono_array_length (cattrs);
1465 /* Skip nonpublic attributes since MS.NET seems to do the same */
1466 /* FIXME: This needs to be done more globally */
1468 for (i = 0; i < count; ++i) {
1469 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1470 if (!custom_attr_visible (image, cattr))
1473 count -= not_visible;
1475 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1477 ainfo->image = image;
1478 ainfo->num_attrs = count;
1479 ainfo->cached = alloc_img != NULL;
1481 for (i = 0; i < count; ++i) {
1482 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1483 if (custom_attr_visible (image, cattr)) {
1484 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1485 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1486 ainfo->attrs [index].ctor = cattr->ctor->method;
1487 ainfo->attrs [index].data = saved;
1488 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1496 #ifndef DISABLE_REFLECTION_EMIT
1498 * LOCKING: Acquires the loader lock.
1501 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1503 MONO_REQ_GC_UNSAFE_MODE;
1505 MonoCustomAttrInfo *ainfo, *tmp;
1507 if (!cattrs || !mono_array_length (cattrs))
1510 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1512 mono_loader_lock ();
1513 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1515 mono_custom_attrs_free (tmp);
1516 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1517 mono_loader_unlock ();
1523 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1525 MONO_REQ_GC_NEUTRAL_MODE;
1527 if (ainfo && !ainfo->cached)
1532 * idx is the table index of the object
1533 * type is one of MONO_CUSTOM_ATTR_*
1536 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1538 MONO_REQ_GC_UNSAFE_MODE;
1540 MonoDynamicTable *table;
1541 MonoReflectionCustomAttr *cattr;
1543 guint32 count, i, token;
1545 char *p = blob_size;
1547 mono_error_init (error);
1549 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1552 count = mono_array_length (cattrs);
1553 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1554 table->rows += count;
1555 alloc_table (table, table->rows);
1556 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1557 idx <<= MONO_CUSTOM_ATTR_BITS;
1559 for (i = 0; i < count; ++i) {
1560 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1561 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1562 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1563 if (!mono_error_ok (error)) goto fail;
1564 type = mono_metadata_token_index (token);
1565 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1566 switch (mono_metadata_token_table (token)) {
1567 case MONO_TABLE_METHOD:
1568 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1570 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1571 * method, not the one returned by mono_image_create_token ().
1573 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1575 case MONO_TABLE_MEMBERREF:
1576 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1579 g_warning ("got wrong token in custom attr");
1582 values [MONO_CUSTOM_ATTR_TYPE] = type;
1584 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1585 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1586 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1587 values += MONO_CUSTOM_ATTR_SIZE;
1598 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1600 MONO_REQ_GC_UNSAFE_MODE;
1602 MonoDynamicTable *table;
1604 guint32 count, i, idx;
1605 MonoReflectionPermissionSet *perm;
1610 count = mono_array_length (permissions);
1611 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1612 table->rows += count;
1613 alloc_table (table, table->rows);
1615 for (i = 0; i < mono_array_length (permissions); ++i) {
1616 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1618 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1620 idx = mono_metadata_token_index (parent_token);
1621 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1622 switch (mono_metadata_token_table (parent_token)) {
1623 case MONO_TABLE_TYPEDEF:
1624 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1626 case MONO_TABLE_METHOD:
1627 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1629 case MONO_TABLE_ASSEMBLY:
1630 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1633 g_assert_not_reached ();
1636 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1637 values [MONO_DECL_SECURITY_PARENT] = idx;
1638 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1645 * Fill in the MethodDef and ParamDef tables for a method.
1646 * This is used for both normal methods and constructors.
1649 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1651 MONO_REQ_GC_UNSAFE_MODE;
1653 MonoDynamicTable *table;
1657 mono_error_init (error);
1659 /* room in this table is already allocated */
1660 table = &assembly->tables [MONO_TABLE_METHOD];
1661 *mb->table_idx = table->next_idx ++;
1662 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1663 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1664 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1665 values [MONO_METHOD_FLAGS] = mb->attrs;
1666 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1667 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1668 return_val_if_nok (error, FALSE);
1669 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1670 return_val_if_nok (error, FALSE);
1672 table = &assembly->tables [MONO_TABLE_PARAM];
1673 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1675 mono_image_add_decl_security (assembly,
1676 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1679 MonoDynamicTable *mtable;
1682 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1683 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1686 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1687 if (mono_array_get (mb->pinfo, gpointer, i))
1690 table->rows += count;
1691 alloc_table (table, table->rows);
1692 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1693 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1694 MonoReflectionParamBuilder *pb;
1695 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1696 values [MONO_PARAM_FLAGS] = pb->attrs;
1697 values [MONO_PARAM_SEQUENCE] = i;
1698 if (pb->name != NULL) {
1699 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1701 values [MONO_PARAM_NAME] = 0;
1703 values += MONO_PARAM_SIZE;
1704 if (pb->marshal_info) {
1706 alloc_table (mtable, mtable->rows);
1707 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1708 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1709 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1710 return_val_if_nok (error, FALSE);
1712 pb->table_idx = table->next_idx++;
1713 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1714 guint32 field_type = 0;
1715 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1717 alloc_table (mtable, mtable->rows);
1718 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1719 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1720 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1721 mvalues [MONO_CONSTANT_TYPE] = field_type;
1722 mvalues [MONO_CONSTANT_PADDING] = 0;
1731 #ifndef DISABLE_REFLECTION_EMIT
1733 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1735 MONO_REQ_GC_UNSAFE_MODE;
1737 mono_error_init (error);
1738 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1740 rmb->ilgen = mb->ilgen;
1741 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1742 return_val_if_nok (error, FALSE);
1743 rmb->parameters = mb->parameters;
1744 rmb->generic_params = mb->generic_params;
1745 rmb->generic_container = mb->generic_container;
1746 rmb->opt_types = NULL;
1747 rmb->pinfo = mb->pinfo;
1748 rmb->attrs = mb->attrs;
1749 rmb->iattrs = mb->iattrs;
1750 rmb->call_conv = mb->call_conv;
1751 rmb->code = mb->code;
1752 rmb->type = mb->type;
1753 rmb->name = mb->name;
1754 rmb->table_idx = &mb->table_idx;
1755 rmb->init_locals = mb->init_locals;
1756 rmb->skip_visibility = FALSE;
1757 rmb->return_modreq = mb->return_modreq;
1758 rmb->return_modopt = mb->return_modopt;
1759 rmb->param_modreq = mb->param_modreq;
1760 rmb->param_modopt = mb->param_modopt;
1761 rmb->permissions = mb->permissions;
1762 rmb->mhandle = mb->mhandle;
1767 rmb->charset = mb->charset;
1768 rmb->extra_flags = mb->extra_flags;
1769 rmb->native_cc = mb->native_cc;
1770 rmb->dllentry = mb->dllentry;
1778 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1780 MONO_REQ_GC_UNSAFE_MODE;
1782 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1784 mono_error_init (error);
1786 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1788 rmb->ilgen = mb->ilgen;
1789 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1790 return_val_if_nok (error, FALSE);
1791 rmb->parameters = mb->parameters;
1792 rmb->generic_params = NULL;
1793 rmb->generic_container = NULL;
1794 rmb->opt_types = NULL;
1795 rmb->pinfo = mb->pinfo;
1796 rmb->attrs = mb->attrs;
1797 rmb->iattrs = mb->iattrs;
1798 rmb->call_conv = mb->call_conv;
1800 rmb->type = mb->type;
1801 rmb->name = mono_string_new (mono_domain_get (), name);
1802 rmb->table_idx = &mb->table_idx;
1803 rmb->init_locals = mb->init_locals;
1804 rmb->skip_visibility = FALSE;
1805 rmb->return_modreq = NULL;
1806 rmb->return_modopt = NULL;
1807 rmb->param_modreq = mb->param_modreq;
1808 rmb->param_modopt = mb->param_modopt;
1809 rmb->permissions = mb->permissions;
1810 rmb->mhandle = mb->mhandle;
1818 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1820 MONO_REQ_GC_UNSAFE_MODE;
1822 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1824 rmb->ilgen = mb->ilgen;
1825 rmb->rtype = mb->rtype;
1826 rmb->parameters = mb->parameters;
1827 rmb->generic_params = NULL;
1828 rmb->generic_container = NULL;
1829 rmb->opt_types = NULL;
1831 rmb->attrs = mb->attrs;
1833 rmb->call_conv = mb->call_conv;
1835 rmb->type = (MonoObject *) mb->owner;
1836 rmb->name = mb->name;
1837 rmb->table_idx = NULL;
1838 rmb->init_locals = mb->init_locals;
1839 rmb->skip_visibility = mb->skip_visibility;
1840 rmb->return_modreq = NULL;
1841 rmb->return_modopt = NULL;
1842 rmb->param_modreq = NULL;
1843 rmb->param_modopt = NULL;
1844 rmb->permissions = NULL;
1845 rmb->mhandle = mb->mhandle;
1852 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1854 MONO_REQ_GC_UNSAFE_MODE;
1856 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1857 MonoDynamicTable *table;
1860 MonoReflectionMethod *m;
1863 mono_error_init (error);
1865 if (!mb->override_methods)
1868 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1869 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1871 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1873 alloc_table (table, table->rows);
1874 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1875 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1876 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1878 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1879 return_val_if_nok (error, FALSE);
1881 switch (mono_metadata_token_table (tok)) {
1882 case MONO_TABLE_MEMBERREF:
1883 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1885 case MONO_TABLE_METHOD:
1886 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1889 g_assert_not_reached ();
1891 values [MONO_METHODIMPL_DECLARATION] = tok;
1897 #ifndef DISABLE_REFLECTION_EMIT
1899 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1901 MONO_REQ_GC_UNSAFE_MODE;
1903 MonoDynamicTable *table;
1905 ReflectionMethodBuilder rmb;
1908 mono_error_init (error);
1910 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1911 !mono_image_basic_method (&rmb, assembly, error))
1914 mb->table_idx = *rmb.table_idx;
1916 if (mb->dll) { /* It's a P/Invoke method */
1918 /* map CharSet values to on-disk values */
1919 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1920 int extra_flags = mb->extra_flags;
1921 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1923 alloc_table (table, table->rows);
1924 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1926 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1927 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1929 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1931 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1932 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1933 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1934 table = &assembly->tables [MONO_TABLE_MODULEREF];
1936 alloc_table (table, table->rows);
1937 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1938 values [MONO_IMPLMAP_SCOPE] = table->rows;
1942 if (mb->generic_params) {
1943 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1944 table->rows += mono_array_length (mb->generic_params);
1945 alloc_table (table, table->rows);
1946 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1947 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1949 mono_image_get_generic_param_info (
1950 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1958 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1960 MONO_REQ_GC_UNSAFE_MODE;
1962 ReflectionMethodBuilder rmb;
1964 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1967 if (!mono_image_basic_method (&rmb, assembly, error))
1970 mb->table_idx = *rmb.table_idx;
1977 type_get_fully_qualified_name (MonoType *type)
1979 MONO_REQ_GC_NEUTRAL_MODE;
1981 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1985 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1987 MONO_REQ_GC_UNSAFE_MODE;
1992 klass = mono_class_from_mono_type (type);
1994 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1995 ta = klass->image->assembly;
1996 if (assembly_is_dynamic (ta) || (ta == ass)) {
1997 if (klass->generic_class || klass->generic_container)
1998 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1999 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2001 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2004 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2007 #ifndef DISABLE_REFLECTION_EMIT
2008 /*field_image is the image to which the eventual custom mods have been encoded against*/
2010 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2012 MONO_REQ_GC_NEUTRAL_MODE;
2015 guint32 idx, i, token;
2017 if (!assembly->save)
2020 sigbuffer_init (&buf, 32);
2022 sigbuffer_add_value (&buf, 0x06);
2023 /* encode custom attributes before the type */
2024 if (type->num_mods) {
2025 for (i = 0; i < type->num_mods; ++i) {
2028 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2029 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2031 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2033 token = type->modifiers [i].token;
2036 if (type->modifiers [i].required)
2037 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2039 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2041 sigbuffer_add_value (&buf, token);
2044 encode_type (assembly, type, &buf);
2045 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2046 sigbuffer_free (&buf);
2052 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2054 MONO_REQ_GC_UNSAFE_MODE;
2056 mono_error_init (error);
2060 guint32 typespec = 0;
2064 init_type_builder_generics (fb->type);
2066 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2067 return_val_if_nok (error, 0);
2068 klass = mono_class_from_mono_type (type);
2070 sigbuffer_init (&buf, 32);
2072 sigbuffer_add_value (&buf, 0x06);
2073 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2076 /* encode custom attributes before the type */
2078 if (klass->generic_container)
2079 typespec = create_typespec (assembly, type);
2082 MonoGenericClass *gclass;
2083 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2084 encode_generic_class (assembly, gclass, &buf);
2086 encode_type (assembly, type, &buf);
2088 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089 sigbuffer_free (&buf);
2092 sigbuffer_free (&buf);
2097 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2099 MONO_REQ_GC_UNSAFE_MODE;
2101 char blob_size [64];
2102 char *b = blob_size;
2105 guint32 idx = 0, len = 0, dummy = 0;
2107 buf = (char *)g_malloc (64);
2109 *ret_type = MONO_TYPE_CLASS;
2111 box_val = (char*)&dummy;
2113 box_val = ((char*)val) + sizeof (MonoObject);
2114 *ret_type = val->vtable->klass->byval_arg.type;
2117 switch (*ret_type) {
2118 case MONO_TYPE_BOOLEAN:
2123 case MONO_TYPE_CHAR:
2140 case MONO_TYPE_VALUETYPE: {
2141 MonoClass *klass = val->vtable->klass;
2143 if (klass->enumtype) {
2144 *ret_type = mono_class_enum_basetype (klass)->type;
2146 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2149 g_error ("we can't encode valuetypes, we should have never reached this line");
2152 case MONO_TYPE_CLASS:
2154 case MONO_TYPE_STRING: {
2155 MonoString *str = (MonoString*)val;
2156 /* there is no signature */
2157 len = str->length * 2;
2158 mono_metadata_encode_value (len, b, &b);
2159 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2161 char *swapped = g_malloc (2 * mono_string_length (str));
2162 const char *p = (const char*)mono_string_chars (str);
2164 swap_with_size (swapped, p, 2, mono_string_length (str));
2165 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2169 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2175 case MONO_TYPE_GENERICINST:
2176 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2179 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2182 /* there is no signature */
2183 mono_metadata_encode_value (len, b, &b);
2184 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2185 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2186 swap_with_size (blob_size, box_val, len, 1);
2187 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2189 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2197 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2199 MONO_REQ_GC_UNSAFE_MODE;
2201 mono_error_init (error);
2207 sigbuffer_init (&buf, 32);
2209 sigbuffer_add_value (&buf, minfo->type);
2211 switch (minfo->type) {
2212 case MONO_NATIVE_BYVALTSTR:
2213 case MONO_NATIVE_BYVALARRAY:
2214 sigbuffer_add_value (&buf, minfo->count);
2216 case MONO_NATIVE_LPARRAY:
2217 if (minfo->eltype || minfo->has_size) {
2218 sigbuffer_add_value (&buf, minfo->eltype);
2219 if (minfo->has_size) {
2220 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2221 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2223 /* LAMESPEC: ElemMult is undocumented */
2224 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2228 case MONO_NATIVE_SAFEARRAY:
2230 sigbuffer_add_value (&buf, minfo->eltype);
2232 case MONO_NATIVE_CUSTOM:
2234 str = mono_string_to_utf8 (minfo->guid);
2236 sigbuffer_add_value (&buf, len);
2237 sigbuffer_add_mem (&buf, str, len);
2240 sigbuffer_add_value (&buf, 0);
2242 /* native type name */
2243 sigbuffer_add_value (&buf, 0);
2244 /* custom marshaler type name */
2245 if (minfo->marshaltype || minfo->marshaltyperef) {
2246 if (minfo->marshaltyperef) {
2247 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2248 if (!is_ok (error)) {
2249 sigbuffer_free (&buf);
2252 str = type_get_fully_qualified_name (marshaltype);
2254 str = mono_string_to_utf8 (minfo->marshaltype);
2256 sigbuffer_add_value (&buf, len);
2257 sigbuffer_add_mem (&buf, str, len);
2260 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2261 sigbuffer_add_value (&buf, 0);
2263 if (minfo->mcookie) {
2264 str = mono_string_to_utf8 (minfo->mcookie);
2266 sigbuffer_add_value (&buf, len);
2267 sigbuffer_add_mem (&buf, str, len);
2270 sigbuffer_add_value (&buf, 0);
2276 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2277 sigbuffer_free (&buf);
2282 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2284 MONO_REQ_GC_UNSAFE_MODE;
2286 mono_error_init (error);
2288 MonoDynamicTable *table;
2291 /* maybe this fixup should be done in the C# code */
2292 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2293 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2294 table = &assembly->tables [MONO_TABLE_FIELD];
2295 fb->table_idx = table->next_idx ++;
2296 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2297 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2298 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2299 values [MONO_FIELD_FLAGS] = fb->attrs;
2300 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2301 return_if_nok (error);
2304 if (fb->offset != -1) {
2305 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2307 alloc_table (table, table->rows);
2308 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2309 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2310 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2312 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2313 MonoTypeEnum field_type = (MonoTypeEnum)0;
2314 table = &assembly->tables [MONO_TABLE_CONSTANT];
2316 alloc_table (table, table->rows);
2317 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2318 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2319 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2320 values [MONO_CONSTANT_TYPE] = field_type;
2321 values [MONO_CONSTANT_PADDING] = 0;
2323 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2325 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2327 alloc_table (table, table->rows);
2328 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2329 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2331 * We store it in the code section because it's simpler for now.
2334 if (mono_array_length (fb->rva_data) >= 10)
2335 stream_data_align (&assembly->code);
2336 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2338 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2339 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2341 if (fb->marshal_info) {
2342 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2344 alloc_table (table, table->rows);
2345 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2346 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2347 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2348 return_if_nok (error);
2353 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2355 MONO_REQ_GC_UNSAFE_MODE;
2357 mono_error_init (error);
2360 guint32 nparams = 0;
2361 MonoReflectionMethodBuilder *mb = fb->get_method;
2362 MonoReflectionMethodBuilder *smb = fb->set_method;
2365 if (mb && mb->parameters)
2366 nparams = mono_array_length (mb->parameters);
2367 if (!mb && smb && smb->parameters)
2368 nparams = mono_array_length (smb->parameters) - 1;
2369 sigbuffer_init (&buf, 32);
2370 if (fb->call_conv & 0x20)
2371 sigbuffer_add_byte (&buf, 0x28);
2373 sigbuffer_add_byte (&buf, 0x08);
2374 sigbuffer_add_value (&buf, nparams);
2376 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2379 for (i = 0; i < nparams; ++i) {
2380 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2381 encode_reflection_type (assembly, pt, &buf, error);
2385 } else if (smb && smb->parameters) {
2386 /* the property type is the last param */
2387 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2391 for (i = 0; i < nparams; ++i) {
2392 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2393 encode_reflection_type (assembly, pt, &buf, error);
2398 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2403 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2404 sigbuffer_free (&buf);
2407 sigbuffer_free (&buf);
2412 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2414 MONO_REQ_GC_UNSAFE_MODE;
2416 mono_error_init (error);
2418 MonoDynamicTable *table;
2420 guint num_methods = 0;
2424 * we need to set things in the following tables:
2425 * PROPERTYMAP (info already filled in _get_type_info ())
2426 * PROPERTY (rows already preallocated in _get_type_info ())
2427 * METHOD (method info already done with the generic method code)
2431 table = &assembly->tables [MONO_TABLE_PROPERTY];
2432 pb->table_idx = table->next_idx ++;
2433 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2434 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2435 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2436 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2437 return_if_nok (error);
2440 /* FIXME: we still don't handle 'other' methods */
2441 if (pb->get_method) num_methods ++;
2442 if (pb->set_method) num_methods ++;
2444 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2445 table->rows += num_methods;
2446 alloc_table (table, table->rows);
2448 if (pb->get_method) {
2449 semaidx = table->next_idx ++;
2450 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2451 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2452 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2453 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2455 if (pb->set_method) {
2456 semaidx = table->next_idx ++;
2457 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2458 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2459 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2460 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2462 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2463 MonoTypeEnum field_type = (MonoTypeEnum)0;
2464 table = &assembly->tables [MONO_TABLE_CONSTANT];
2466 alloc_table (table, table->rows);
2467 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2468 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2469 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2470 values [MONO_CONSTANT_TYPE] = field_type;
2471 values [MONO_CONSTANT_PADDING] = 0;
2476 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2478 MONO_REQ_GC_UNSAFE_MODE;
2480 MonoDynamicTable *table;
2482 guint num_methods = 0;
2486 * we need to set things in the following tables:
2487 * EVENTMAP (info already filled in _get_type_info ())
2488 * EVENT (rows already preallocated in _get_type_info ())
2489 * METHOD (method info already done with the generic method code)
2492 table = &assembly->tables [MONO_TABLE_EVENT];
2493 eb->table_idx = table->next_idx ++;
2494 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2495 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2496 values [MONO_EVENT_FLAGS] = eb->attrs;
2497 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2498 return_if_nok (error);
2499 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2502 * FIXME: we still don't handle 'other' methods
2504 if (eb->add_method) num_methods ++;
2505 if (eb->remove_method) num_methods ++;
2506 if (eb->raise_method) num_methods ++;
2508 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2509 table->rows += num_methods;
2510 alloc_table (table, table->rows);
2512 if (eb->add_method) {
2513 semaidx = table->next_idx ++;
2514 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2515 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2516 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2517 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2519 if (eb->remove_method) {
2520 semaidx = table->next_idx ++;
2521 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2522 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2523 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2524 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2526 if (eb->raise_method) {
2527 semaidx = table->next_idx ++;
2528 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2529 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2530 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2531 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2536 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2538 MONO_REQ_GC_UNSAFE_MODE;
2540 mono_error_init (error);
2542 MonoDynamicTable *table;
2543 guint32 num_constraints, i;
2547 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2548 num_constraints = gparam->iface_constraints ?
2549 mono_array_length (gparam->iface_constraints) : 0;
2550 table->rows += num_constraints;
2551 if (gparam->base_type)
2553 alloc_table (table, table->rows);
2555 if (gparam->base_type) {
2556 table_idx = table->next_idx ++;
2557 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2559 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2560 return_if_nok (error);
2561 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2562 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2565 for (i = 0; i < num_constraints; i++) {
2566 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2567 gparam->iface_constraints, gpointer, i);
2569 table_idx = table->next_idx ++;
2570 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2572 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2573 return_if_nok (error);
2575 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2576 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2581 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2583 MONO_REQ_GC_UNSAFE_MODE;
2585 GenericParamTableEntry *entry;
2588 * The GenericParam table must be sorted according to the `owner' field.
2589 * We need to do this sorting prior to writing the GenericParamConstraint
2590 * table, since we have to use the final GenericParam table indices there
2591 * and they must also be sorted.
2594 entry = g_new0 (GenericParamTableEntry, 1);
2595 entry->owner = owner;
2596 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2597 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2598 entry->gparam = gparam;
2600 g_ptr_array_add (assembly->gen_params, entry);
2604 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2606 MONO_REQ_GC_UNSAFE_MODE;
2608 MonoDynamicTable *table;
2609 MonoGenericParam *param;
2613 mono_error_init (error);
2615 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2616 table_idx = table->next_idx ++;
2617 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2619 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2620 return_val_if_nok (error, FALSE);
2622 param = gparam_type->data.generic_param;
2624 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2625 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2626 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2627 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2629 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2632 encode_constraints (entry->gparam, table_idx, assembly, error);
2633 return_val_if_nok (error, FALSE);
2639 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2641 MONO_REQ_GC_UNSAFE_MODE;
2643 MonoDynamicTable *table;
2646 guint32 cols [MONO_ASSEMBLY_SIZE];
2650 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2653 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2654 table = &assembly->tables [MONO_TABLE_MODULEREF];
2655 token = table->next_idx ++;
2657 alloc_table (table, table->rows);
2658 values = table->values + token * MONO_MODULEREF_SIZE;
2659 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2661 token <<= MONO_RESOLUTION_SCOPE_BITS;
2662 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2663 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2668 if (assembly_is_dynamic (image->assembly))
2670 memset (cols, 0, sizeof (cols));
2672 /* image->assembly->image is the manifest module */
2673 image = image->assembly->image;
2674 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2677 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2678 token = table->next_idx ++;
2680 alloc_table (table, table->rows);
2681 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2682 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2683 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2684 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2685 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2686 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2687 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2688 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2689 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2691 if (strcmp ("", image->assembly->aname.culture)) {
2692 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2693 image->assembly->aname.culture);
2696 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2697 guchar pubtoken [9];
2699 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2700 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2702 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2704 token <<= MONO_RESOLUTION_SCOPE_BITS;
2705 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2706 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2711 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2713 MONO_REQ_GC_NEUTRAL_MODE;
2715 MonoDynamicTable *table;
2720 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2723 sigbuffer_init (&buf, 32);
2724 switch (type->type) {
2725 case MONO_TYPE_FNPTR:
2727 case MONO_TYPE_SZARRAY:
2728 case MONO_TYPE_ARRAY:
2730 case MONO_TYPE_MVAR:
2731 case MONO_TYPE_GENERICINST:
2732 encode_type (assembly, type, &buf);
2734 case MONO_TYPE_CLASS:
2735 case MONO_TYPE_VALUETYPE: {
2736 MonoClass *k = mono_class_from_mono_type (type);
2737 if (!k || !k->generic_container) {
2738 sigbuffer_free (&buf);
2741 encode_type (assembly, type, &buf);
2745 sigbuffer_free (&buf);
2749 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2750 if (assembly->save) {
2751 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2752 alloc_table (table, table->rows + 1);
2753 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2754 values [MONO_TYPESPEC_SIGNATURE] = token;
2756 sigbuffer_free (&buf);
2758 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2759 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2765 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2767 MONO_REQ_GC_UNSAFE_MODE;
2769 MonoDynamicTable *table;
2771 guint32 token, scope, enclosing;
2774 /* if the type requires a typespec, we must try that first*/
2775 if (try_typespec && (token = create_typespec (assembly, type)))
2777 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2780 klass = mono_class_from_mono_type (type);
2782 klass = mono_class_from_mono_type (type);
2785 * If it's in the same module and not a generic type parameter:
2787 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2788 (type->type != MONO_TYPE_MVAR)) {
2789 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2790 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2791 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2795 if (klass->nested_in) {
2796 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2797 /* get the typeref idx of the enclosing type */
2798 enclosing >>= MONO_TYPEDEFORREF_BITS;
2799 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2801 scope = resolution_scope_from_image (assembly, klass->image);
2803 table = &assembly->tables [MONO_TABLE_TYPEREF];
2804 if (assembly->save) {
2805 alloc_table (table, table->rows + 1);
2806 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2807 values [MONO_TYPEREF_SCOPE] = scope;
2808 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2809 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2811 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2812 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2814 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2819 * Despite the name, we handle also TypeSpec (with the above helper).
2822 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2824 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2827 #ifndef DISABLE_REFLECTION_EMIT
2829 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2831 MONO_REQ_GC_NEUTRAL_MODE;
2833 MonoDynamicTable *table;
2835 guint32 token, pclass;
2837 switch (parent & MONO_TYPEDEFORREF_MASK) {
2838 case MONO_TYPEDEFORREF_TYPEREF:
2839 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2841 case MONO_TYPEDEFORREF_TYPESPEC:
2842 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2844 case MONO_TYPEDEFORREF_TYPEDEF:
2845 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2848 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2851 /* extract the index */
2852 parent >>= MONO_TYPEDEFORREF_BITS;
2854 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2856 if (assembly->save) {
2857 alloc_table (table, table->rows + 1);
2858 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2859 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2860 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2861 values [MONO_MEMBERREF_SIGNATURE] = sig;
2864 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2871 * Insert a memberef row into the metadata: the token that point to the memberref
2872 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2873 * mono_image_get_fieldref_token()).
2874 * The sig param is an index to an already built signature.
2877 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2879 MONO_REQ_GC_NEUTRAL_MODE;
2881 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2882 return mono_image_add_memberef_row (assembly, parent, name, sig);
2887 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2889 MONO_REQ_GC_NEUTRAL_MODE;
2892 MonoMethodSignature *sig;
2894 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2896 if (create_typespec) {
2897 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2902 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2903 if (token && !create_typespec)
2906 g_assert (!method->is_inflated);
2909 * A methodref signature can't contain an unmanaged calling convention.
2911 sig = mono_metadata_signature_dup (mono_method_signature (method));
2912 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2913 sig->call_convention = MONO_CALL_DEFAULT;
2914 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2915 method->name, method_encode_signature (assembly, sig));
2917 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2920 if (create_typespec) {
2921 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2922 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2923 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2925 if (assembly->save) {
2928 alloc_table (table, table->rows + 1);
2929 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2930 values [MONO_METHODSPEC_METHOD] = token;
2931 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2934 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2936 /*methodspec and memberef tokens are diferent, */
2937 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2944 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2946 guint32 token, parent, sig;
2947 ReflectionMethodBuilder rmb;
2948 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2950 mono_error_init (error);
2951 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2955 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2959 * A methodref signature can't contain an unmanaged calling convention.
2960 * Since some flags are encoded as part of call_conv, we need to check against it.
2962 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2963 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2965 sig = method_builder_encode_signature (assembly, &rmb, error);
2966 return_val_if_nok (error, 0);
2968 if (tb->generic_params) {
2969 parent = create_generic_typespec (assembly, tb, error);
2970 return_val_if_nok (error, 0);
2972 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2973 return_val_if_nok (error, 0);
2975 parent = mono_image_typedef_or_ref (assembly, t);
2978 char *name = mono_string_to_utf8 (method->name);
2980 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2983 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2989 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2990 const gchar *name, guint32 sig)
2992 MonoDynamicTable *table;
2996 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2998 if (assembly->save) {
2999 alloc_table (table, table->rows + 1);
3000 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3001 values [MONO_MEMBERREF_CLASS] = original;
3002 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3003 values [MONO_MEMBERREF_SIGNATURE] = sig;
3006 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3013 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3017 guint32 nparams = mono_array_length (mb->generic_params);
3020 if (!assembly->save)
3023 sigbuffer_init (&buf, 32);
3025 sigbuffer_add_value (&buf, 0xa);
3026 sigbuffer_add_value (&buf, nparams);
3028 for (i = 0; i < nparams; i++) {
3029 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3030 sigbuffer_add_value (&buf, i);
3033 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034 sigbuffer_free (&buf);
3039 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3041 MonoDynamicTable *table;
3043 guint32 token, mtoken = 0;
3045 mono_error_init (error);
3046 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3050 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3052 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3053 if (!mono_error_ok (error))
3056 switch (mono_metadata_token_table (mtoken)) {
3057 case MONO_TABLE_MEMBERREF:
3058 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3060 case MONO_TABLE_METHOD:
3061 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3064 g_assert_not_reached ();
3067 if (assembly->save) {
3068 alloc_table (table, table->rows + 1);
3069 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3070 values [MONO_METHODSPEC_METHOD] = mtoken;
3071 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3074 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3077 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3082 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3086 mono_error_init (error);
3088 if (mb->generic_params && create_methodspec)
3089 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3091 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3095 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3096 if (!mono_error_ok (error))
3098 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3103 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3105 guint32 token, parent, sig;
3106 ReflectionMethodBuilder rmb;
3108 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3110 mono_error_init (error);
3112 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3116 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3119 if (tb->generic_params) {
3120 parent = create_generic_typespec (assembly, tb, error);
3121 return_val_if_nok (error, 0);
3123 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3124 return_val_if_nok (error, 0);
3125 parent = mono_image_typedef_or_ref (assembly, type);
3128 name = mono_string_to_utf8 (rmb.name);
3129 sig = method_builder_encode_signature (assembly, &rmb, error);
3130 return_val_if_nok (error, 0);
3132 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3135 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3141 is_field_on_inst (MonoClassField *field)
3143 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3147 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3150 get_field_on_inst_generic_type (MonoClassField *field)
3152 MonoClass *klass, *gtd;
3153 MonoDynamicGenericClass *dgclass;
3156 g_assert (is_field_on_inst (field));
3158 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3160 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3161 field_index = field - dgclass->fields;
3162 return dgclass->field_generic_types [field_index];
3165 klass = field->parent;
3166 gtd = klass->generic_class->container_class;
3168 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3169 field_index = field - klass->fields;
3170 return gtd->fields [field_index].type;
3173 g_assert_not_reached ();
3177 #ifndef DISABLE_REFLECTION_EMIT
3179 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3185 g_assert (field->parent);
3187 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3191 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3192 int index = field - field->parent->fields;
3193 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3195 if (is_field_on_inst (field))
3196 type = get_field_on_inst_generic_type (field);
3198 type = mono_field_get_type (field);
3200 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3201 mono_field_get_name (field),
3202 fieldref_encode_signature (assembly, field->parent->image, type));
3203 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3208 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3212 MonoGenericClass *gclass;
3216 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3219 if (is_sre_field_builder (mono_object_class (f->fb))) {
3220 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3221 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3222 return_val_if_nok (error, 0);
3223 klass = mono_class_from_mono_type (type);
3224 gclass = type->data.generic_class;
3225 g_assert (gclass->is_dynamic);
3227 guint32 sig_token = field_encode_signature (assembly, fb, error);
3228 return_val_if_nok (error, 0);
3229 name = mono_string_to_utf8 (fb->name);
3230 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3232 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3234 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3236 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3237 return_val_if_nok (error, 0);
3238 klass = mono_class_from_mono_type (type);
3240 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3241 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3243 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3244 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3247 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3252 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3256 MonoGenericClass *gclass;
3259 mono_error_init (error);
3261 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3263 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3267 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3268 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3269 ReflectionMethodBuilder rmb;
3272 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3273 return_val_if_nok (error, 0);
3274 klass = mono_class_from_mono_type (type);
3276 gclass = type->data.generic_class;
3277 g_assert (gclass->is_dynamic);
3279 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3282 sig = method_builder_encode_signature (assembly, &rmb, error);
3283 return_val_if_nok (error, 0);
3285 name = mono_string_to_utf8 (rmb.name);
3287 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3289 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3290 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3292 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3293 return_val_if_nok (error, 0);
3294 klass = mono_class_from_mono_type (type);
3296 sig = method_encode_signature (assembly, mono_method_signature (mm));
3297 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3299 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3300 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3304 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3309 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3312 MonoGenericContext tmp_context;
3313 MonoType **type_argv;
3314 MonoGenericInst *ginst;
3315 MonoMethod *method, *inflated;
3318 mono_error_init (error);
3320 init_type_builder_generics ((MonoObject*)m->inst);
3322 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3323 return_val_if_nok (error, NULL);
3325 klass = method->klass;
3327 if (m->method_args == NULL)
3330 if (method->is_inflated)
3331 method = ((MonoMethodInflated *) method)->declaring;
3333 count = mono_array_length (m->method_args);
3335 type_argv = g_new0 (MonoType *, count);
3336 for (i = 0; i < count; i++) {
3337 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3338 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3339 return_val_if_nok (error, NULL);
3341 ginst = mono_metadata_get_generic_inst (count, type_argv);
3344 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3345 tmp_context.method_inst = ginst;
3347 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3348 mono_error_assert_ok (error);
3353 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3355 guint32 sig, token = 0;
3359 mono_error_init (error);
3361 if (m->method_args) {
3362 MonoMethod *inflated;
3364 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3365 return_val_if_nok (error, 0);
3367 if (create_methodspec)
3368 token = mono_image_get_methodspec_token (assembly, inflated);
3370 token = mono_image_get_inflated_method_token (assembly, inflated);
3374 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3378 if (is_sre_method_builder (mono_object_class (m->mb))) {
3379 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3380 MonoGenericClass *gclass;
3381 ReflectionMethodBuilder rmb;
3384 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3385 return_val_if_nok (error, 0);
3386 klass = mono_class_from_mono_type (type);
3387 gclass = type->data.generic_class;
3388 g_assert (gclass->is_dynamic);
3390 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3393 sig = method_builder_encode_signature (assembly, &rmb, error);
3394 return_val_if_nok (error, 0);
3396 name = mono_string_to_utf8 (rmb.name);
3398 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3400 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3401 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3403 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3404 return_val_if_nok (error, 0);
3405 klass = mono_class_from_mono_type (type);
3407 sig = method_encode_signature (assembly, mono_method_signature (mm));
3408 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3410 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3411 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3414 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3419 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3423 guint32 nparams = context->method_inst->type_argc;
3426 if (!assembly->save)
3429 sigbuffer_init (&buf, 32);
3431 * FIXME: vararg, explicit_this, differenc call_conv values...
3433 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3434 sigbuffer_add_value (&buf, nparams);
3436 for (i = 0; i < nparams; i++)
3437 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3439 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3440 sigbuffer_free (&buf);
3445 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3447 MonoDynamicTable *table;
3449 guint32 token, mtoken = 0, sig;
3450 MonoMethodInflated *imethod;
3451 MonoMethod *declaring;
3453 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3455 g_assert (method->is_inflated);
3456 imethod = (MonoMethodInflated *) method;
3457 declaring = imethod->declaring;
3459 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3460 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3462 if (!mono_method_signature (declaring)->generic_param_count)
3465 switch (mono_metadata_token_table (mtoken)) {
3466 case MONO_TABLE_MEMBERREF:
3467 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3469 case MONO_TABLE_METHOD:
3470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3473 g_assert_not_reached ();
3476 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3478 if (assembly->save) {
3479 alloc_table (table, table->rows + 1);
3480 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3481 values [MONO_METHODSPEC_METHOD] = mtoken;
3482 values [MONO_METHODSPEC_SIGNATURE] = sig;
3485 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3492 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3494 MonoMethodInflated *imethod;
3497 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3501 g_assert (method->is_inflated);
3502 imethod = (MonoMethodInflated *) method;
3504 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3505 token = method_encode_methodspec (assembly, method);
3507 guint32 sig = method_encode_signature (
3508 assembly, mono_method_signature (imethod->declaring));
3509 token = mono_image_get_memberref_token (
3510 assembly, &method->klass->byval_arg, method->name, sig);
3513 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3518 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3520 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3523 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3524 token = mono_image_get_memberref_token (
3525 assembly, &m->klass->byval_arg, m->name, sig);
3531 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3533 MonoDynamicTable *table;
3542 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3543 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3544 * Because of this, we must not insert it into the `typeref' hash table.
3546 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3547 return_val_if_nok (error, 0);
3548 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3552 sigbuffer_init (&buf, 32);
3554 g_assert (tb->generic_params);
3555 klass = mono_class_from_mono_type (type);
3557 if (tb->generic_container)
3558 mono_reflection_create_generic_class (tb);
3560 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3561 g_assert (klass->generic_container);
3562 sigbuffer_add_value (&buf, klass->byval_arg.type);
3563 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3565 count = mono_array_length (tb->generic_params);
3566 sigbuffer_add_value (&buf, count);
3567 for (i = 0; i < count; i++) {
3568 MonoReflectionGenericParam *gparam;
3570 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3571 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3575 encode_type (assembly, gparam_type, &buf);
3578 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3580 if (assembly->save) {
3581 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3582 alloc_table (table, table->rows + 1);
3583 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3584 values [MONO_TYPESPEC_SIGNATURE] = token;
3586 sigbuffer_free (&buf);
3588 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3589 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3593 sigbuffer_free (&buf);
3598 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3601 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3603 int i, count, len, pos;
3606 mono_error_init (error);
3610 count += mono_array_length (modreq);
3612 count += mono_array_length (modopt);
3615 return mono_metadata_type_dup (NULL, type);
3617 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3618 t = (MonoType *)g_malloc (len);
3619 memcpy (t, type, MONO_SIZEOF_TYPE);
3621 t->num_mods = count;
3624 for (i = 0; i < mono_array_length (modreq); ++i) {
3625 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3628 t->modifiers [pos].required = 1;
3629 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3634 for (i = 0; i < mono_array_length (modopt); ++i) {
3635 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3638 t->modifiers [pos].required = 0;
3639 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3651 init_type_builder_generics (MonoObject *type)
3653 MonoReflectionTypeBuilder *tb;
3655 if (!is_sre_type_builder(mono_object_class (type)))
3657 tb = (MonoReflectionTypeBuilder *)type;
3659 if (tb && tb->generic_container)
3660 mono_reflection_create_generic_class (tb);
3664 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3666 MonoDynamicTable *table;
3667 MonoType *custom = NULL, *type;
3669 guint32 token, pclass, parent, sig;
3672 mono_error_init (error);
3674 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3678 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3679 return_val_if_nok (error, 0);
3680 /* FIXME: is this call necessary? */
3681 mono_class_from_mono_type (typeb);
3683 /*FIXME this is one more layer of ugliness due how types are created.*/
3684 init_type_builder_generics (fb->type);
3686 /* fb->type does not include the custom modifiers */
3687 /* FIXME: We should do this in one place when a fieldbuilder is created */
3688 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3689 return_val_if_nok (error, 0);
3691 if (fb->modreq || fb->modopt) {
3692 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3693 return_val_if_nok (error, 0);
3696 sig = fieldref_encode_signature (assembly, NULL, type);
3699 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3700 return_val_if_nok (error, 0);
3701 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3703 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3704 parent >>= MONO_TYPEDEFORREF_BITS;
3706 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3708 name = mono_string_to_utf8 (fb->name);
3710 if (assembly->save) {
3711 alloc_table (table, table->rows + 1);
3712 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3713 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3714 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3715 values [MONO_MEMBERREF_SIGNATURE] = sig;
3718 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3720 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3726 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3732 mono_error_init (error);
3734 if (!assembly->save)
3737 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3738 g_assert (helper->type == 2);
3740 if (helper->arguments)
3741 nargs = mono_array_length (helper->arguments);
3745 sigbuffer_init (&buf, 32);
3747 /* Encode calling convention */
3748 /* Change Any to Standard */
3749 if ((helper->call_conv & 0x03) == 0x03)
3750 helper->call_conv = 0x01;
3751 /* explicit_this implies has_this */
3752 if (helper->call_conv & 0x40)
3753 helper->call_conv &= 0x20;
3755 if (helper->call_conv == 0) { /* Unmanaged */
3756 idx = helper->unmanaged_call_conv - 1;
3759 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3760 if (helper->call_conv & 0x02) /* varargs */
3764 sigbuffer_add_byte (&buf, idx);
3765 sigbuffer_add_value (&buf, nargs);
3766 encode_reflection_type (assembly, helper->return_type, &buf, error);
3769 for (i = 0; i < nargs; ++i) {
3770 MonoArray *modreqs = NULL;
3771 MonoArray *modopts = NULL;
3772 MonoReflectionType *pt;
3774 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3775 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3776 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3777 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3779 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3782 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3783 encode_reflection_type (assembly, pt, &buf, error);
3787 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3788 sigbuffer_free (&buf);
3792 sigbuffer_free (&buf);
3797 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3800 MonoDynamicTable *table;
3803 mono_error_init (error);
3805 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3806 idx = table->next_idx ++;
3808 alloc_table (table, table->rows);
3809 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3811 values [MONO_STAND_ALONE_SIGNATURE] =
3812 mono_reflection_encode_sighelper (assembly, helper, error);
3813 return_val_if_nok (error, 0);
3819 reflection_cc_to_file (int call_conv) {
3820 switch (call_conv & 0x3) {
3822 case 1: return MONO_CALL_DEFAULT;
3823 case 2: return MONO_CALL_VARARG;
3825 g_assert_not_reached ();
3829 #endif /* !DISABLE_REFLECTION_EMIT */
3833 MonoMethodSignature *sig;
3838 #ifndef DISABLE_REFLECTION_EMIT
3840 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3845 MonoMethodSignature *sig;
3846 ArrayMethod *am = NULL;
3849 mono_error_init (error);
3851 nparams = mono_array_length (m->parameters);
3852 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3854 sig->sentinelpos = -1;
3855 sig->call_convention = reflection_cc_to_file (m->call_conv);
3856 sig->param_count = nparams;
3858 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3862 sig->ret = &mono_defaults.void_class->byval_arg;
3864 mtype = mono_reflection_type_get_handle (m->parent, error);
3868 for (i = 0; i < nparams; ++i) {
3869 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3874 name = mono_string_to_utf8 (m->name);
3875 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3876 am = (ArrayMethod *)tmp->data;
3877 if (strcmp (name, am->name) == 0 &&
3878 mono_metadata_type_equal (am->parent, mtype) &&
3879 mono_metadata_signature_equal (am->sig, sig)) {
3882 m->table_idx = am->token & 0xffffff;
3886 am = g_new0 (ArrayMethod, 1);
3890 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3891 method_encode_signature (assembly, sig));
3892 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3893 m->table_idx = am->token & 0xffffff;
3904 * Insert into the metadata tables all the info about the TypeBuilder tb.
3905 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3908 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3910 MonoDynamicTable *table;
3912 int i, is_object = 0, is_system = 0;
3915 mono_error_init (error);
3917 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3918 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3919 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3920 n = mono_string_to_utf8 (tb->name);
3921 if (strcmp (n, "Object") == 0)
3923 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3925 n = mono_string_to_utf8 (tb->nspace);
3926 if (strcmp (n, "System") == 0)
3928 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3930 if (tb->parent && !(is_system && is_object) &&
3931 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3932 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3933 return_val_if_nok (error, FALSE);
3934 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3936 values [MONO_TYPEDEF_EXTENDS] = 0;
3938 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3939 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3942 * if we have explicitlayout or sequentiallayouts, output data in the
3943 * ClassLayout table.
3945 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3946 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3947 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3949 alloc_table (table, table->rows);
3950 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3951 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3952 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3953 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3956 /* handle interfaces */
3957 if (tb->interfaces) {
3958 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3960 table->rows += mono_array_length (tb->interfaces);
3961 alloc_table (table, table->rows);
3962 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3963 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3964 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3965 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3966 return_val_if_nok (error, FALSE);
3967 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3968 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3969 values += MONO_INTERFACEIMPL_SIZE;
3975 table = &assembly->tables [MONO_TABLE_FIELD];
3976 table->rows += tb->num_fields;
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < tb->num_fields; ++i) {
3979 mono_image_get_field_info (
3980 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3981 return_val_if_nok (error, FALSE);
3985 /* handle constructors */
3987 table = &assembly->tables [MONO_TABLE_METHOD];
3988 table->rows += mono_array_length (tb->ctors);
3989 alloc_table (table, table->rows);
3990 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3991 if (!mono_image_get_ctor_info (domain,
3992 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3998 /* handle methods */
4000 table = &assembly->tables [MONO_TABLE_METHOD];
4001 table->rows += tb->num_methods;
4002 alloc_table (table, table->rows);
4003 for (i = 0; i < tb->num_methods; ++i) {
4004 if (!mono_image_get_method_info (
4005 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4010 /* Do the same with properties etc.. */
4011 if (tb->events && mono_array_length (tb->events)) {
4012 table = &assembly->tables [MONO_TABLE_EVENT];
4013 table->rows += mono_array_length (tb->events);
4014 alloc_table (table, table->rows);
4015 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4017 alloc_table (table, table->rows);
4018 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4019 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4020 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4021 for (i = 0; i < mono_array_length (tb->events); ++i) {
4022 mono_image_get_event_info (
4023 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4024 return_val_if_nok (error, FALSE);
4027 if (tb->properties && mono_array_length (tb->properties)) {
4028 table = &assembly->tables [MONO_TABLE_PROPERTY];
4029 table->rows += mono_array_length (tb->properties);
4030 alloc_table (table, table->rows);
4031 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4033 alloc_table (table, table->rows);
4034 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4035 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4036 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4037 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4038 mono_image_get_property_info (
4039 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4040 return_val_if_nok (error, FALSE);
4044 /* handle generic parameters */
4045 if (tb->generic_params) {
4046 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4047 table->rows += mono_array_length (tb->generic_params);
4048 alloc_table (table, table->rows);
4049 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4050 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4052 mono_image_get_generic_param_info (
4053 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4057 mono_image_add_decl_security (assembly,
4058 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4061 MonoDynamicTable *ntable;
4063 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4064 ntable->rows += mono_array_length (tb->subtypes);
4065 alloc_table (ntable, ntable->rows);
4066 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4068 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4069 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4071 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4072 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4073 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4074 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4075 mono_string_to_utf8 (tb->name), tb->table_idx,
4076 ntable->next_idx, ntable->rows);*/
4077 values += MONO_NESTED_CLASS_SIZE;
4087 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4091 mono_ptr_array_append (*types, type);
4093 if (!type->subtypes)
4096 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4097 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4098 collect_types (types, subtype);
4103 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4105 if ((*type1)->table_idx < (*type2)->table_idx)
4108 if ((*type1)->table_idx > (*type2)->table_idx)
4115 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4118 mono_error_init (error);
4121 for (i = 0; i < mono_array_length (pinfo); ++i) {
4122 MonoReflectionParamBuilder *pb;
4123 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4126 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4134 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4137 mono_error_init (error);
4139 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4142 for (i = 0; i < tb->num_fields; ++i) {
4143 MonoReflectionFieldBuilder* fb;
4144 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4145 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4150 for (i = 0; i < mono_array_length (tb->events); ++i) {
4151 MonoReflectionEventBuilder* eb;
4152 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4153 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4157 if (tb->properties) {
4158 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4159 MonoReflectionPropertyBuilder* pb;
4160 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4161 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4166 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4167 MonoReflectionCtorBuilder* cb;
4168 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4169 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4170 !params_add_cattrs (assembly, cb->pinfo, error))
4176 for (i = 0; i < tb->num_methods; ++i) {
4177 MonoReflectionMethodBuilder* mb;
4178 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4179 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4180 !params_add_cattrs (assembly, mb->pinfo, error))
4186 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4187 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4196 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4200 mono_error_init (error);
4202 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4205 if (moduleb->global_methods) {
4206 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4207 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4208 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4209 !params_add_cattrs (assembly, mb->pinfo, error))
4214 if (moduleb->global_fields) {
4215 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4216 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4217 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4222 if (moduleb->types) {
4223 for (i = 0; i < moduleb->num_types; ++i) {
4224 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4233 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4235 MonoDynamicTable *table;
4239 char *b = blob_size;
4242 table = &assembly->tables [MONO_TABLE_FILE];
4244 alloc_table (table, table->rows);
4245 values = table->values + table->next_idx * MONO_FILE_SIZE;
4246 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4247 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4248 if (image_is_dynamic (module->image)) {
4249 /* This depends on the fact that the main module is emitted last */
4250 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4251 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4254 path = g_strdup (module->image->name);
4256 mono_sha1_get_digest_from_file (path, hash);
4259 mono_metadata_encode_value (20, b, &b);
4260 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4261 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4266 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4268 MonoDynamicTable *table;
4271 table = &assembly->tables [MONO_TABLE_MODULE];
4272 mb->table_idx = table->next_idx ++;
4273 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4274 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4277 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4278 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4279 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4280 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4284 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4285 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4287 MonoDynamicTable *table;
4291 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4292 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4295 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4297 alloc_table (table, table->rows);
4298 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4300 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4301 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4302 if (klass->nested_in)
4303 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4305 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4306 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4307 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4309 res = table->next_idx;
4313 /* Emit nested types */
4314 if (klass->ext && klass->ext->nested_classes) {
4317 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4318 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4325 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4326 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4332 mono_error_init (error);
4334 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4335 return_if_nok (error);
4337 klass = mono_class_from_mono_type (t);
4339 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4341 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4342 parent_index, assembly);
4346 * We need to do this ourselves since klass->nested_classes is not set up.
4349 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4350 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4351 return_if_nok (error);
4357 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4358 guint32 module_index, MonoDynamicImage *assembly)
4360 MonoImage *image = module->image;
4364 t = &image->tables [MONO_TABLE_TYPEDEF];
4366 for (i = 0; i < t->rows; ++i) {
4368 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4369 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4371 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4372 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4377 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4379 MonoDynamicTable *table;
4381 guint32 scope, scope_idx, impl, current_idx;
4382 gboolean forwarder = TRUE;
4383 gpointer iter = NULL;
4386 if (klass->nested_in) {
4387 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4390 scope = resolution_scope_from_image (assembly, klass->image);
4391 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4392 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4393 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4396 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4399 alloc_table (table, table->rows);
4400 current_idx = table->next_idx;
4401 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4403 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4404 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4405 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4406 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4407 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4411 while ((nested = mono_class_get_nested_types (klass, &iter)))
4412 add_exported_type (assemblyb, assembly, nested, current_idx);
4416 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4422 if (!assemblyb->type_forwarders)
4425 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4426 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4431 type = mono_reflection_type_get_handle (t, &error);
4432 mono_error_assert_ok (&error);
4435 klass = mono_class_from_mono_type (type);
4437 add_exported_type (assemblyb, assembly, klass, 0);
4441 #define align_pointer(base,p)\
4443 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4445 (p) += 4 - (__diff & 3);\
4449 compare_constants (const void *a, const void *b)
4451 const guint32 *a_values = (const guint32 *)a;
4452 const guint32 *b_values = (const guint32 *)b;
4453 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4457 compare_semantics (const void *a, const void *b)
4459 const guint32 *a_values = (const guint32 *)a;
4460 const guint32 *b_values = (const guint32 *)b;
4461 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4464 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4468 compare_custom_attrs (const void *a, const void *b)
4470 const guint32 *a_values = (const guint32 *)a;
4471 const guint32 *b_values = (const guint32 *)b;
4473 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4477 compare_field_marshal (const void *a, const void *b)
4479 const guint32 *a_values = (const guint32 *)a;
4480 const guint32 *b_values = (const guint32 *)b;
4482 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4486 compare_nested (const void *a, const void *b)
4488 const guint32 *a_values = (const guint32 *)a;
4489 const guint32 *b_values = (const guint32 *)b;
4491 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4495 compare_genericparam (const void *a, const void *b)
4498 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4499 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4501 if ((*b_entry)->owner == (*a_entry)->owner) {
4502 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4503 mono_error_assert_ok (&error);
4504 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4505 mono_error_assert_ok (&error);
4507 mono_type_get_generic_param_num (a_type) -
4508 mono_type_get_generic_param_num (b_type);
4510 return (*a_entry)->owner - (*b_entry)->owner;
4514 compare_declsecurity_attrs (const void *a, const void *b)
4516 const guint32 *a_values = (const guint32 *)a;
4517 const guint32 *b_values = (const guint32 *)b;
4519 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4523 compare_interface_impl (const void *a, const void *b)
4525 const guint32 *a_values = (const guint32 *)a;
4526 const guint32 *b_values = (const guint32 *)b;
4528 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4532 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4536 pad_heap (MonoDynamicStream *sh)
4538 if (sh->index & 3) {
4539 int sz = 4 - (sh->index & 3);
4540 memset (sh->data + sh->index, 0, sz);
4547 MonoDynamicStream *stream;
4551 * build_compressed_metadata() fills in the blob of data that represents the
4552 * raw metadata as it will be saved in the PE file. The five streams are output
4553 * and the metadata tables are comnpressed from the guint32 array representation,
4554 * to the compressed on-disk format.
4557 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4559 MonoDynamicTable *table;
4561 guint64 valid_mask = 0;
4562 guint64 sorted_mask;
4563 guint32 heapt_size = 0;
4564 guint32 meta_size = 256; /* allow for header and other stuff */
4565 guint32 table_offset;
4566 guint32 ntables = 0;
4572 struct StreamDesc stream_desc [5];
4574 mono_error_init (error);
4576 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4577 for (i = 0; i < assembly->gen_params->len; i++) {
4578 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4579 if (!write_generic_param_entry (assembly, entry, error))
4583 stream_desc [0].name = "#~";
4584 stream_desc [0].stream = &assembly->tstream;
4585 stream_desc [1].name = "#Strings";
4586 stream_desc [1].stream = &assembly->sheap;
4587 stream_desc [2].name = "#US";
4588 stream_desc [2].stream = &assembly->us;
4589 stream_desc [3].name = "#Blob";
4590 stream_desc [3].stream = &assembly->blob;
4591 stream_desc [4].name = "#GUID";
4592 stream_desc [4].stream = &assembly->guid;
4594 /* tables that are sorted */
4595 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4596 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4597 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4598 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4599 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4600 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4601 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4603 /* Compute table sizes */
4604 /* the MonoImage has already been created in mono_image_basic_init() */
4605 meta = &assembly->image;
4607 /* sizes should be multiple of 4 */
4608 pad_heap (&assembly->blob);
4609 pad_heap (&assembly->guid);
4610 pad_heap (&assembly->sheap);
4611 pad_heap (&assembly->us);
4613 /* Setup the info used by compute_sizes () */
4614 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4615 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4616 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4618 meta_size += assembly->blob.index;
4619 meta_size += assembly->guid.index;
4620 meta_size += assembly->sheap.index;
4621 meta_size += assembly->us.index;
4623 for (i=0; i < MONO_TABLE_NUM; ++i)
4624 meta->tables [i].rows = assembly->tables [i].rows;
4626 for (i = 0; i < MONO_TABLE_NUM; i++){
4627 if (meta->tables [i].rows == 0)
4629 valid_mask |= (guint64)1 << i;
4631 meta->tables [i].row_size = mono_metadata_compute_size (
4632 meta, i, &meta->tables [i].size_bitfield);
4633 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4635 heapt_size += 24; /* #~ header size */
4636 heapt_size += ntables * 4;
4637 /* make multiple of 4 */
4640 meta_size += heapt_size;
4641 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4642 p = (unsigned char*)meta->raw_metadata;
4643 /* the metadata signature */
4644 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4645 /* version numbers and 4 bytes reserved */
4646 int16val = (guint16*)p;
4647 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4648 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4650 /* version string */
4651 int32val = (guint32*)p;
4652 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4654 memcpy (p, meta->version, strlen (meta->version));
4655 p += GUINT32_FROM_LE (*int32val);
4656 align_pointer (meta->raw_metadata, p);
4657 int16val = (guint16*)p;
4658 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4659 *int16val = GUINT16_TO_LE (5); /* number of streams */
4663 * write the stream info.
4665 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4666 table_offset += 3; table_offset &= ~3;
4668 assembly->tstream.index = heapt_size;
4669 for (i = 0; i < 5; ++i) {
4670 int32val = (guint32*)p;
4671 stream_desc [i].stream->offset = table_offset;
4672 *int32val++ = GUINT32_TO_LE (table_offset);
4673 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4674 table_offset += GUINT32_FROM_LE (*int32val);
4675 table_offset += 3; table_offset &= ~3;
4677 strcpy ((char*)p, stream_desc [i].name);
4678 p += strlen (stream_desc [i].name) + 1;
4679 align_pointer (meta->raw_metadata, p);
4682 * now copy the data, the table stream header and contents goes first.
4684 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4685 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4686 int32val = (guint32*)p;
4687 *int32val = GUINT32_TO_LE (0); /* reserved */
4690 *p++ = 2; /* version */
4693 if (meta->idx_string_wide)
4695 if (meta->idx_guid_wide)
4697 if (meta->idx_blob_wide)
4700 *p++ = 1; /* reserved */
4701 int64val = (guint64*)p;
4702 *int64val++ = GUINT64_TO_LE (valid_mask);
4703 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4705 int32val = (guint32*)p;
4706 for (i = 0; i < MONO_TABLE_NUM; i++){
4707 if (meta->tables [i].rows == 0)
4709 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4711 p = (unsigned char*)int32val;
4713 /* sort the tables that still need sorting */
4714 table = &assembly->tables [MONO_TABLE_CONSTANT];
4716 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4717 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4719 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4720 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4722 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4723 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4725 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4726 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4728 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4729 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4730 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4732 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4733 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4735 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4737 /* compress the tables */
4738 for (i = 0; i < MONO_TABLE_NUM; i++){
4741 guint32 bitfield = meta->tables [i].size_bitfield;
4742 if (!meta->tables [i].rows)
4744 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4745 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4746 meta->tables [i].base = (char*)p;
4747 for (row = 1; row <= meta->tables [i].rows; ++row) {
4748 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4749 for (col = 0; col < assembly->tables [i].columns; ++col) {
4750 switch (mono_metadata_table_size (bitfield, col)) {
4752 *p++ = values [col];
4755 *p++ = values [col] & 0xff;
4756 *p++ = (values [col] >> 8) & 0xff;
4759 *p++ = values [col] & 0xff;
4760 *p++ = (values [col] >> 8) & 0xff;
4761 *p++ = (values [col] >> 16) & 0xff;
4762 *p++ = (values [col] >> 24) & 0xff;
4765 g_assert_not_reached ();
4769 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4772 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4773 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4774 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4775 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4776 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4778 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4784 * Some tables in metadata need to be sorted according to some criteria, but
4785 * when methods and fields are first created with reflection, they may be assigned a token
4786 * that doesn't correspond to the final token they will get assigned after the sorting.
4787 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4788 * with the reflection objects that represent them. Once all the tables are set up, the
4789 * reflection objects will contains the correct table index. fixup_method() will fixup the
4790 * tokens for the method with ILGenerator @ilgen.
4793 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4795 guint32 code_idx = GPOINTER_TO_UINT (value);
4796 MonoReflectionILTokenInfo *iltoken;
4797 MonoReflectionFieldBuilder *field;
4798 MonoReflectionCtorBuilder *ctor;
4799 MonoReflectionMethodBuilder *method;
4800 MonoReflectionTypeBuilder *tb;
4801 MonoReflectionArrayMethod *am;
4803 unsigned char *target;
4805 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4806 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4807 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4808 switch (target [3]) {
4809 case MONO_TABLE_FIELD:
4810 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4811 field = (MonoReflectionFieldBuilder *)iltoken->member;
4812 idx = field->table_idx;
4813 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4814 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4815 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4817 g_assert_not_reached ();
4820 case MONO_TABLE_METHOD:
4821 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4822 method = (MonoReflectionMethodBuilder *)iltoken->member;
4823 idx = method->table_idx;
4824 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4825 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4826 idx = ctor->table_idx;
4827 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4828 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4829 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4830 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4832 g_assert_not_reached ();
4835 case MONO_TABLE_TYPEDEF:
4836 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4837 g_assert_not_reached ();
4838 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4839 idx = tb->table_idx;
4841 case MONO_TABLE_MEMBERREF:
4842 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4843 am = (MonoReflectionArrayMethod*)iltoken->member;
4844 idx = am->table_idx;
4845 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4846 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4847 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4848 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4849 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4850 g_assert (m->klass->generic_class || m->klass->generic_container);
4852 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4854 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4855 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4856 g_assert (is_field_on_inst (f));
4858 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4859 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4861 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4863 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4865 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4868 g_assert_not_reached ();
4871 case MONO_TABLE_METHODSPEC:
4872 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4873 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4874 g_assert (mono_method_signature (m)->generic_param_count);
4876 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4878 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4881 g_assert_not_reached ();
4885 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4887 target [0] = idx & 0xff;
4888 target [1] = (idx >> 8) & 0xff;
4889 target [2] = (idx >> 16) & 0xff;
4896 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4897 * value is not known when the table is emitted.
4900 fixup_cattrs (MonoDynamicImage *assembly)
4902 MonoDynamicTable *table;
4904 guint32 type, i, idx, token;
4907 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4909 for (i = 0; i < table->rows; ++i) {
4910 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4912 type = values [MONO_CUSTOM_ATTR_TYPE];
4913 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4914 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4915 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4916 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4919 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4920 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4921 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4922 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4923 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4924 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4925 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4926 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4933 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4935 MonoDynamicTable *table;
4938 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4940 alloc_table (table, table->rows);
4941 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4942 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4943 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4944 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4945 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4950 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4952 MonoDynamicTable *table;
4956 char *b = blob_size;
4958 guint32 idx, offset;
4960 if (rsrc->filename) {
4961 name = mono_string_to_utf8 (rsrc->filename);
4962 sname = g_path_get_basename (name);
4964 table = &assembly->tables [MONO_TABLE_FILE];
4966 alloc_table (table, table->rows);
4967 values = table->values + table->next_idx * MONO_FILE_SIZE;
4968 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4969 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4972 mono_sha1_get_digest_from_file (name, hash);
4973 mono_metadata_encode_value (20, b, &b);
4974 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4975 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4977 idx = table->next_idx++;
4979 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4985 data = mono_array_addr (rsrc->data, char, 0);
4986 len = mono_array_length (rsrc->data);
4992 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4993 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4994 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4995 mono_image_add_stream_data (&assembly->resources, data, len);
4999 * The entry should be emitted into the MANIFESTRESOURCE table of
5000 * the main module, but that needs to reference the FILE table
5001 * which isn't emitted yet.
5008 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5012 set_version_from_string (MonoString *version, guint32 *values)
5014 gchar *ver, *p, *str;
5017 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5018 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5019 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5020 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5023 ver = str = mono_string_to_utf8 (version);
5024 for (i = 0; i < 4; ++i) {
5025 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5031 /* handle Revision and Build */
5041 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5045 char *b = blob_size;
5050 len = mono_array_length (pkey);
5051 mono_metadata_encode_value (len, b, &b);
5052 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5053 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5055 assembly->public_key = (guint8 *)g_malloc (len);
5056 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5057 assembly->public_key_len = len;
5059 /* Special case: check for ECMA key (16 bytes) */
5060 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5061 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5062 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5063 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5064 /* minimum key size (in 2.0) is 384 bits */
5065 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5067 /* FIXME - verifier */
5068 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5069 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5071 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5077 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5079 MonoDynamicTable *table;
5080 MonoDynamicImage *assembly;
5081 MonoReflectionAssemblyBuilder *assemblyb;
5085 guint32 module_index;
5087 mono_error_init (error);
5089 assemblyb = moduleb->assemblyb;
5090 assembly = moduleb->dynamic_image;
5091 domain = mono_object_domain (assemblyb);
5093 /* Emit ASSEMBLY table */
5094 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5095 alloc_table (table, 1);
5096 values = table->values + MONO_ASSEMBLY_SIZE;
5097 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5098 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5099 if (assemblyb->culture) {
5100 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5102 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5104 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5105 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5106 set_version_from_string (assemblyb->version, values);
5108 /* Emit FILE + EXPORTED_TYPE table */
5110 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5112 MonoReflectionModuleBuilder *file_module =
5113 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5114 if (file_module != moduleb) {
5115 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5117 if (file_module->types) {
5118 for (j = 0; j < file_module->num_types; ++j) {
5119 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5120 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5121 return_if_nok (error);
5126 if (assemblyb->loaded_modules) {
5127 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5128 MonoReflectionModule *file_module =
5129 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5130 mono_image_fill_file_table (domain, file_module, assembly);
5132 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5135 if (assemblyb->type_forwarders)
5136 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5138 /* Emit MANIFESTRESOURCE table */
5140 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5142 MonoReflectionModuleBuilder *file_module =
5143 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5144 /* The table for the main module is emitted later */
5145 if (file_module != moduleb) {
5147 if (file_module->resources) {
5148 int len = mono_array_length (file_module->resources);
5149 for (j = 0; j < len; ++j) {
5150 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5151 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5161 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5162 * for the modulebuilder @moduleb.
5163 * At the end of the process, method and field tokens are fixed up and the
5164 * on-disk compressed metadata representation is created.
5165 * Return TRUE on success, or FALSE on failure and sets @error
5168 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5170 MonoDynamicTable *table;
5171 MonoDynamicImage *assembly;
5172 MonoReflectionAssemblyBuilder *assemblyb;
5178 mono_error_init (error);
5180 assemblyb = moduleb->assemblyb;
5181 assembly = moduleb->dynamic_image;
5182 domain = mono_object_domain (assemblyb);
5184 if (assembly->text_rva)
5187 assembly->text_rva = START_TEXT_RVA;
5189 if (moduleb->is_main) {
5190 mono_image_emit_manifest (moduleb, error);
5191 return_val_if_nok (error, FALSE);
5194 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5195 table->rows = 1; /* .<Module> */
5197 alloc_table (table, table->rows);
5199 * Set the first entry.
5201 values = table->values + table->columns;
5202 values [MONO_TYPEDEF_FLAGS] = 0;
5203 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5204 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5205 values [MONO_TYPEDEF_EXTENDS] = 0;
5206 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5207 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5210 * handle global methods
5211 * FIXME: test what to do when global methods are defined in multiple modules.
5213 if (moduleb->global_methods) {
5214 table = &assembly->tables [MONO_TABLE_METHOD];
5215 table->rows += mono_array_length (moduleb->global_methods);
5216 alloc_table (table, table->rows);
5217 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5218 if (!mono_image_get_method_info (
5219 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5223 if (moduleb->global_fields) {
5224 table = &assembly->tables [MONO_TABLE_FIELD];
5225 table->rows += mono_array_length (moduleb->global_fields);
5226 alloc_table (table, table->rows);
5227 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5228 mono_image_get_field_info (
5229 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5236 table = &assembly->tables [MONO_TABLE_MODULE];
5237 alloc_table (table, 1);
5238 mono_image_fill_module_table (domain, moduleb, assembly);
5240 /* Collect all types into a list sorted by their table_idx */
5241 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5244 for (i = 0; i < moduleb->num_types; ++i) {
5245 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5246 collect_types (&types, type);
5249 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5250 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5251 table->rows += mono_ptr_array_size (types);
5252 alloc_table (table, table->rows);
5255 * Emit type names + namespaces at one place inside the string heap,
5256 * so load_class_names () needs to touch fewer pages.
5258 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5259 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5260 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5262 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5263 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5264 string_heap_insert_mstring (&assembly->sheap, tb->name);
5267 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5268 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5269 if (!mono_image_get_type_info (domain, type, assembly, error))
5274 * table->rows is already set above and in mono_image_fill_module_table.
5276 /* add all the custom attributes at the end, once all the indexes are stable */
5277 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5280 /* CAS assembly permissions */
5281 if (assemblyb->permissions_minimum)
5282 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5283 if (assemblyb->permissions_optional)
5284 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5285 if (assemblyb->permissions_refused)
5286 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5288 if (!module_add_cattrs (assembly, moduleb, error))
5292 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5294 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5295 * the final tokens and don't need another fixup pass. */
5297 if (moduleb->global_methods) {
5298 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5299 MonoReflectionMethodBuilder *mb = mono_array_get (
5300 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5301 if (!mono_image_add_methodimpl (assembly, mb, error))
5306 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5307 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5308 if (type->methods) {
5309 for (j = 0; j < type->num_methods; ++j) {
5310 MonoReflectionMethodBuilder *mb = mono_array_get (
5311 type->methods, MonoReflectionMethodBuilder*, j);
5313 if (!mono_image_add_methodimpl (assembly, mb, error))
5319 fixup_cattrs (assembly);
5322 mono_ptr_array_destroy (types);
5325 return mono_error_ok (error);
5328 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5331 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5333 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5336 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5340 guint32 import_lookup_table;
5344 guint32 import_address_table_rva;
5352 #ifndef DISABLE_REFLECTION_EMIT
5355 * mono_image_insert_string:
5356 * @module: module builder object
5359 * Insert @str into the user string stream of @module.
5362 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5364 MonoDynamicImage *assembly;
5369 if (!module->dynamic_image)
5370 mono_image_module_basic_init (module);
5372 assembly = module->dynamic_image;
5374 if (assembly->save) {
5375 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5376 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5377 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5379 char *swapped = g_malloc (2 * mono_string_length (str));
5380 const char *p = (const char*)mono_string_chars (str);
5382 swap_with_size (swapped, p, 2, mono_string_length (str));
5383 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5387 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5389 mono_image_add_stream_data (&assembly->us, "", 1);
5391 idx = assembly->us.index ++;
5394 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5396 return MONO_TOKEN_STRING | idx;
5400 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5404 MonoMethodSignature *sig;
5406 mono_error_init (error);
5408 klass = obj->vtable->klass;
5409 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5410 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5411 MonoMethodSignature *old;
5412 guint32 sig_token, parent;
5415 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5417 nargs = mono_array_length (opt_param_types);
5418 old = mono_method_signature (method);
5419 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5421 sig->hasthis = old->hasthis;
5422 sig->explicit_this = old->explicit_this;
5423 sig->call_convention = old->call_convention;
5424 sig->generic_param_count = old->generic_param_count;
5425 sig->param_count = old->param_count + nargs;
5426 sig->sentinelpos = old->param_count;
5427 sig->ret = old->ret;
5429 for (i = 0; i < old->param_count; i++)
5430 sig->params [i] = old->params [i];
5432 for (i = 0; i < nargs; i++) {
5433 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5434 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5435 if (!is_ok (error)) goto fail;
5438 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5439 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5440 parent >>= MONO_TYPEDEFORREF_BITS;
5442 parent <<= MONO_MEMBERREF_PARENT_BITS;
5443 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5445 sig_token = method_encode_signature (assembly, sig);
5446 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5447 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5448 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5449 ReflectionMethodBuilder rmb;
5450 guint32 parent, sig_token;
5451 int nopt_args, nparams, ngparams, i;
5453 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5456 rmb.opt_types = opt_param_types;
5457 nopt_args = mono_array_length (opt_param_types);
5459 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5460 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5461 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5463 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5464 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5465 sig->call_convention = rmb.call_conv;
5466 sig->generic_param_count = ngparams;
5467 sig->param_count = nparams + nopt_args;
5468 sig->sentinelpos = nparams;
5469 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5470 if (!is_ok (error)) goto fail;
5472 for (i = 0; i < nparams; i++) {
5473 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5474 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5475 if (!is_ok (error)) goto fail;
5478 for (i = 0; i < nopt_args; i++) {
5479 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5480 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5481 if (!is_ok (error)) goto fail;
5484 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5488 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5489 if (!mono_error_ok (error))
5491 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5493 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5494 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5496 char *name = mono_string_to_utf8 (rmb.name);
5497 token = mono_image_get_varargs_method_token (
5498 assembly, parent, name, sig_token);
5501 g_error ("requested method token for %s\n", klass->name);
5504 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5505 register_dyn_token (assembly, token, obj);
5508 g_assert (!mono_error_ok (error));
5513 * mono_image_create_token:
5514 * @assembly: a dynamic assembly
5516 * @register_token: Whenever to register the token in the assembly->tokens hash.
5518 * Get a token to insert in the IL code stream for the given MemberInfo.
5519 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5520 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5524 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5525 gboolean create_open_instance, gboolean register_token,
5531 mono_error_init (error);
5533 klass = obj->vtable->klass;
5535 /* Check for user defined reflection objects */
5536 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5537 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5538 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5542 if (strcmp (klass->name, "MethodBuilder") == 0) {
5543 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5544 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5546 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5547 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5549 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5550 if (!mono_error_ok (error))
5553 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5554 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5555 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5556 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5558 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5559 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5561 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5562 if (!mono_error_ok (error))
5565 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5566 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5567 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5568 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5569 if (tb->generic_params) {
5570 token = mono_image_get_generic_field_token (assembly, fb, error);
5571 return_val_if_nok (error, 0);
5573 if (tb->module->dynamic_image == assembly) {
5574 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5576 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5579 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5581 if (create_open_instance && tb->generic_params) {
5583 init_type_builder_generics (obj);
5584 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5585 return_val_if_nok (error, 0);
5586 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5587 token = mono_metadata_token_from_dor (token);
5588 } else if (tb->module->dynamic_image == assembly) {
5589 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5592 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5593 return_val_if_nok (error, 0);
5594 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5596 } else if (strcmp (klass->name, "MonoType") == 0) {
5597 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5598 return_val_if_nok (error, 0);
5599 MonoClass *mc = mono_class_from_mono_type (type);
5600 token = mono_metadata_token_from_dor (
5601 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5602 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5603 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5604 return_val_if_nok (error, 0);
5605 token = mono_metadata_token_from_dor (
5606 mono_image_typedef_or_ref (assembly, type));
5607 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5608 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5609 return_val_if_nok (error, 0);
5610 token = mono_metadata_token_from_dor (
5611 mono_image_typedef_or_ref (assembly, type));
5612 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5613 strcmp (klass->name, "MonoMethod") == 0 ||
5614 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5615 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5616 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5617 if (m->method->is_inflated) {
5618 if (create_open_instance)
5619 token = mono_image_get_methodspec_token (assembly, m->method);
5621 token = mono_image_get_inflated_method_token (assembly, m->method);
5622 } else if ((m->method->klass->image == &assembly->image) &&
5623 !m->method->klass->generic_class) {
5624 static guint32 method_table_idx = 0xffffff;
5625 if (m->method->klass->wastypebuilder) {
5626 /* we use the same token as the one that was assigned
5627 * to the Methodbuilder.
5628 * FIXME: do the equivalent for Fields.
5630 token = m->method->token;
5633 * Each token should have a unique index, but the indexes are
5634 * assigned by managed code, so we don't know about them. An
5635 * easy solution is to count backwards...
5637 method_table_idx --;
5638 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5641 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5643 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5644 } else if (strcmp (klass->name, "MonoField") == 0) {
5645 MonoReflectionField *f = (MonoReflectionField *)obj;
5646 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5647 static guint32 field_table_idx = 0xffffff;
5649 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5651 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5653 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5654 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5655 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5656 token = mono_image_get_array_token (assembly, m, error);
5657 return_val_if_nok (error, 0);
5658 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5659 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5660 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5661 return_val_if_nok (error, 0);
5662 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5663 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5664 return_val_if_nok (error, 0);
5665 token = mono_metadata_token_from_dor (
5666 mono_image_typedef_or_ref (assembly, type));
5667 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5668 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5669 token = mono_image_get_field_on_inst_token (assembly, f, error);
5670 return_val_if_nok (error, 0);
5671 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5672 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5673 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5674 if (!mono_error_ok (error))
5676 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5677 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5678 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5679 if (!mono_error_ok (error))
5681 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5682 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5683 return_val_if_nok (error, 0);
5684 token = mono_metadata_token_from_dor (
5685 mono_image_typedef_or_ref (assembly, type));
5687 g_error ("requested token for %s\n", klass->name);
5691 mono_image_register_token (assembly, token, obj);
5697 * mono_image_register_token:
5699 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5700 * the Module.ResolveXXXToken () methods to work.
5703 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5707 dynamic_image_lock (assembly);
5708 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5710 /* There could be multiple MethodInfo objects with the same token */
5711 //g_assert (prev == obj);
5713 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5715 dynamic_image_unlock (assembly);
5718 static MonoDynamicImage*
5719 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5721 static const guchar entrycode [16] = {0xff, 0x25, 0};
5722 MonoDynamicImage *image;
5725 const char *version;
5727 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5728 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5730 version = mono_get_runtime_info ()->runtime_version;
5733 /* The MonoGHashTable's need GC tracking */
5734 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5736 image = g_new0 (MonoDynamicImage, 1);
5739 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5741 /*g_print ("created image %p\n", image);*/
5742 /* keep in sync with image.c */
5743 image->image.name = assembly_name;
5744 image->image.assembly_name = image->image.name; /* they may be different */
5745 image->image.module_name = module_name;
5746 image->image.version = g_strdup (version);
5747 image->image.md_version_major = 1;
5748 image->image.md_version_minor = 1;
5749 image->image.dynamic = TRUE;
5751 image->image.references = g_new0 (MonoAssembly*, 1);
5752 image->image.references [0] = NULL;
5754 mono_image_init (&image->image);
5756 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");
5757 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5758 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5759 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5760 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5761 image->handleref = g_hash_table_new (NULL, NULL);
5762 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");
5763 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5764 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");
5765 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");
5766 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5767 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5768 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5769 image->gen_params = g_ptr_array_new ();
5770 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5772 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5773 string_heap_init (&image->sheap);
5774 mono_image_add_stream_data (&image->us, "", 1);
5775 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5776 /* import tables... */
5777 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5778 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5779 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5780 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5781 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5782 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5783 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5784 stream_data_align (&image->code);
5786 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5788 for (i=0; i < MONO_TABLE_NUM; ++i) {
5789 image->tables [i].next_idx = 1;
5790 image->tables [i].columns = table_sizes [i];
5793 image->image.assembly = (MonoAssembly*)assembly;
5794 image->run = assembly->run;
5795 image->save = assembly->save;
5796 image->pe_kind = 0x1; /* ILOnly */
5797 image->machine = 0x14c; /* I386 */
5799 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5801 dynamic_images_lock ();
5803 if (!dynamic_images)
5804 dynamic_images = g_ptr_array_new ();
5806 g_ptr_array_add (dynamic_images, image);
5808 dynamic_images_unlock ();
5815 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5821 release_hashtable (MonoGHashTable **hash)
5824 mono_g_hash_table_destroy (*hash);
5830 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5832 release_hashtable (&image->token_fixups);
5833 release_hashtable (&image->handleref_managed);
5834 release_hashtable (&image->tokens);
5835 release_hashtable (&image->remapped_tokens);
5836 release_hashtable (&image->generic_def_objects);
5837 release_hashtable (&image->methodspec);
5840 // Free dynamic image pass one: Free resources but not image itself
5842 mono_dynamic_image_free (MonoDynamicImage *image)
5844 MonoDynamicImage *di = image;
5849 mono_g_hash_table_destroy (di->methodspec);
5851 g_hash_table_destroy (di->typespec);
5853 g_hash_table_destroy (di->typeref);
5855 g_hash_table_destroy (di->handleref);
5856 if (di->handleref_managed)
5857 mono_g_hash_table_destroy (di->handleref_managed);
5859 mono_g_hash_table_destroy (di->tokens);
5860 if (di->remapped_tokens)
5861 mono_g_hash_table_destroy (di->remapped_tokens);
5862 if (di->generic_def_objects)
5863 mono_g_hash_table_destroy (di->generic_def_objects);
5864 if (di->blob_cache) {
5865 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5866 g_hash_table_destroy (di->blob_cache);
5868 if (di->standalonesig_cache)
5869 g_hash_table_destroy (di->standalonesig_cache);
5870 for (list = di->array_methods; list; list = list->next) {
5871 ArrayMethod *am = (ArrayMethod *)list->data;
5876 g_list_free (di->array_methods);
5877 if (di->gen_params) {
5878 for (i = 0; i < di->gen_params->len; i++) {
5879 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5880 mono_gc_deregister_root ((char*) &entry->gparam);
5883 g_ptr_array_free (di->gen_params, TRUE);
5885 if (di->token_fixups)
5886 mono_g_hash_table_destroy (di->token_fixups);
5887 if (di->method_to_table_idx)
5888 g_hash_table_destroy (di->method_to_table_idx);
5889 if (di->field_to_table_idx)
5890 g_hash_table_destroy (di->field_to_table_idx);
5891 if (di->method_aux_hash)
5892 g_hash_table_destroy (di->method_aux_hash);
5893 if (di->vararg_aux_hash)
5894 g_hash_table_destroy (di->vararg_aux_hash);
5895 g_free (di->strong_name);
5896 g_free (di->win32_res);
5898 g_free (di->public_key);
5900 /*g_print ("string heap destroy for image %p\n", di);*/
5901 mono_dynamic_stream_reset (&di->sheap);
5902 mono_dynamic_stream_reset (&di->code);
5903 mono_dynamic_stream_reset (&di->resources);
5904 mono_dynamic_stream_reset (&di->us);
5905 mono_dynamic_stream_reset (&di->blob);
5906 mono_dynamic_stream_reset (&di->tstream);
5907 mono_dynamic_stream_reset (&di->guid);
5908 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5909 g_free (di->tables [i].values);
5912 dynamic_images_lock ();
5915 g_ptr_array_remove (dynamic_images, di);
5917 dynamic_images_unlock ();
5920 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5922 mono_dynamic_image_free_image (MonoDynamicImage *image)
5924 /* See create_dynamic_mono_image () */
5926 /* Allocated using GC_MALLOC */
5932 #ifndef DISABLE_REFLECTION_EMIT
5935 * mono_image_basic_init:
5936 * @assembly: an assembly builder object
5938 * Create the MonoImage that represents the assembly builder and setup some
5939 * of the helper hash table and the basic metadata streams.
5942 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5944 MonoDynamicAssembly *assembly;
5945 MonoDynamicImage *image;
5946 MonoDomain *domain = mono_object_domain (assemblyb);
5948 if (assemblyb->dynamic_assembly)
5952 /* assembly->assembly.image might be GC allocated */
5953 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5955 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5958 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5960 assembly->assembly.ref_count = 1;
5961 assembly->assembly.dynamic = TRUE;
5962 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5963 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5964 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5965 if (assemblyb->culture)
5966 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5968 assembly->assembly.aname.culture = g_strdup ("");
5970 if (assemblyb->version) {
5971 char *vstr = mono_string_to_utf8 (assemblyb->version);
5972 char **version = g_strsplit (vstr, ".", 4);
5973 char **parts = version;
5974 assembly->assembly.aname.major = atoi (*parts++);
5975 assembly->assembly.aname.minor = atoi (*parts++);
5976 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5977 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5979 g_strfreev (version);
5982 assembly->assembly.aname.major = 0;
5983 assembly->assembly.aname.minor = 0;
5984 assembly->assembly.aname.build = 0;
5985 assembly->assembly.aname.revision = 0;
5988 assembly->run = assemblyb->access != 2;
5989 assembly->save = assemblyb->access != 1;
5990 assembly->domain = domain;
5992 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5993 image->initial_image = TRUE;
5994 assembly->assembly.aname.name = image->image.name;
5995 assembly->assembly.image = &image->image;
5996 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5997 /* -1 to correct for the trailing NULL byte */
5998 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5999 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6001 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6004 mono_domain_assemblies_lock (domain);
6005 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6006 mono_domain_assemblies_unlock (domain);
6008 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6010 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6012 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6015 #endif /* !DISABLE_REFLECTION_EMIT */
6017 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6020 calc_section_size (MonoDynamicImage *assembly)
6024 /* alignment constraints */
6025 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6026 g_assert ((assembly->code.index % 4) == 0);
6027 assembly->meta_size += 3;
6028 assembly->meta_size &= ~3;
6029 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6030 g_assert ((assembly->resources.index % 4) == 0);
6032 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6033 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6036 if (assembly->win32_res) {
6037 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6039 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6040 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6044 assembly->sections [MONO_SECTION_RELOC].size = 12;
6045 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6055 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6059 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6061 ResTreeNode *t1 = (ResTreeNode*)a;
6062 ResTreeNode *t2 = (ResTreeNode*)b;
6064 return t1->id - t2->id;
6068 * resource_tree_create:
6070 * Organize the resources into a resource tree.
6072 static ResTreeNode *
6073 resource_tree_create (MonoArray *win32_resources)
6075 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6079 tree = g_new0 (ResTreeNode, 1);
6081 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6082 MonoReflectionWin32Resource *win32_res =
6083 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6087 /* FIXME: BUG: this stores managed references in unmanaged memory */
6088 lang_node = g_new0 (ResTreeNode, 1);
6089 lang_node->id = win32_res->lang_id;
6090 lang_node->win32_res = win32_res;
6092 /* Create type node if neccesary */
6094 for (l = tree->children; l; l = l->next)
6095 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6096 type_node = (ResTreeNode*)l->data;
6101 type_node = g_new0 (ResTreeNode, 1);
6102 type_node->id = win32_res->res_type;
6105 * The resource types have to be sorted otherwise
6106 * Windows Explorer can't display the version information.
6108 tree->children = g_slist_insert_sorted (tree->children,
6109 type_node, resource_tree_compare_by_id);
6112 /* Create res node if neccesary */
6114 for (l = type_node->children; l; l = l->next)
6115 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6116 res_node = (ResTreeNode*)l->data;
6121 res_node = g_new0 (ResTreeNode, 1);
6122 res_node->id = win32_res->res_id;
6123 type_node->children = g_slist_append (type_node->children, res_node);
6126 res_node->children = g_slist_append (res_node->children, lang_node);
6133 * resource_tree_encode:
6135 * Encode the resource tree into the format used in the PE file.
6138 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6141 MonoPEResourceDir dir;
6142 MonoPEResourceDirEntry dir_entry;
6143 MonoPEResourceDataEntry data_entry;
6145 guint32 res_id_entries;
6148 * For the format of the resource directory, see the article
6149 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6153 memset (&dir, 0, sizeof (dir));
6154 memset (&dir_entry, 0, sizeof (dir_entry));
6155 memset (&data_entry, 0, sizeof (data_entry));
6157 g_assert (sizeof (dir) == 16);
6158 g_assert (sizeof (dir_entry) == 8);
6159 g_assert (sizeof (data_entry) == 16);
6161 node->offset = p - begin;
6163 /* IMAGE_RESOURCE_DIRECTORY */
6164 res_id_entries = g_slist_length (node->children);
6165 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6167 memcpy (p, &dir, sizeof (dir));
6170 /* Reserve space for entries */
6172 p += sizeof (dir_entry) * res_id_entries;
6174 /* Write children */
6175 for (l = node->children; l; l = l->next) {
6176 ResTreeNode *child = (ResTreeNode*)l->data;
6178 if (child->win32_res) {
6181 child->offset = p - begin;
6183 /* IMAGE_RESOURCE_DATA_ENTRY */
6184 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6185 size = mono_array_length (child->win32_res->res_data);
6186 data_entry.rde_size = GUINT32_TO_LE (size);
6188 memcpy (p, &data_entry, sizeof (data_entry));
6189 p += sizeof (data_entry);
6191 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6194 resource_tree_encode (child, begin, p, &p);
6198 /* IMAGE_RESOURCE_ENTRY */
6199 for (l = node->children; l; l = l->next) {
6200 ResTreeNode *child = (ResTreeNode*)l->data;
6202 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6203 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6205 memcpy (entries, &dir_entry, sizeof (dir_entry));
6206 entries += sizeof (dir_entry);
6213 resource_tree_free (ResTreeNode * node)
6216 for (list = node->children; list; list = list->next)
6217 resource_tree_free ((ResTreeNode*)list->data);
6218 g_slist_free(node->children);
6223 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6228 MonoReflectionWin32Resource *win32_res;
6231 if (!assemblyb->win32_resources)
6235 * Resources are stored in a three level tree inside the PE file.
6236 * - level one contains a node for each type of resource
6237 * - level two contains a node for each resource
6238 * - level three contains a node for each instance of a resource for a
6239 * specific language.
6242 tree = resource_tree_create (assemblyb->win32_resources);
6244 /* Estimate the size of the encoded tree */
6246 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6247 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6248 size += mono_array_length (win32_res->res_data);
6250 /* Directory structure */
6251 size += mono_array_length (assemblyb->win32_resources) * 256;
6252 p = buf = (char *)g_malloc (size);
6254 resource_tree_encode (tree, p, p, &p);
6256 g_assert (p - buf <= size);
6258 assembly->win32_res = (char *)g_malloc (p - buf);
6259 assembly->win32_res_size = p - buf;
6260 memcpy (assembly->win32_res, buf, p - buf);
6263 resource_tree_free (tree);
6267 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6269 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6272 p += sizeof (MonoPEResourceDir);
6273 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6274 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6275 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6276 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6277 fixup_resource_directory (res_section, child, rva);
6279 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6280 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6283 p += sizeof (MonoPEResourceDirEntry);
6288 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6291 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6292 g_error ("WriteFile returned %d\n", GetLastError ());
6296 * mono_image_create_pefile:
6297 * @mb: a module builder object
6299 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6300 * assembly->pefile where it can be easily retrieved later in chunks.
6303 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6305 MonoMSDOSHeader *msdos;
6306 MonoDotNetHeader *header;
6307 MonoSectionTable *section;
6308 MonoCLIHeader *cli_header;
6309 guint32 size, image_size, virtual_base, text_offset;
6310 guint32 header_start, section_start, file_offset, virtual_offset;
6311 MonoDynamicImage *assembly;
6312 MonoReflectionAssemblyBuilder *assemblyb;
6313 MonoDynamicStream pefile_stream = {0};
6314 MonoDynamicStream *pefile = &pefile_stream;
6316 guint32 *rva, value;
6318 static const unsigned char msheader[] = {
6319 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6320 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6323 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6324 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6325 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6326 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6329 mono_error_init (error);
6331 assemblyb = mb->assemblyb;
6333 mono_image_basic_init (assemblyb);
6334 assembly = mb->dynamic_image;
6336 assembly->pe_kind = assemblyb->pe_kind;
6337 assembly->machine = assemblyb->machine;
6338 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6339 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6341 if (!mono_image_build_metadata (mb, error))
6345 if (mb->is_main && assemblyb->resources) {
6346 int len = mono_array_length (assemblyb->resources);
6347 for (i = 0; i < len; ++i)
6348 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6351 if (mb->resources) {
6352 int len = mono_array_length (mb->resources);
6353 for (i = 0; i < len; ++i)
6354 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6357 if (!build_compressed_metadata (assembly, error))
6361 assembly_add_win32_resources (assembly, assemblyb);
6363 nsections = calc_section_size (assembly);
6365 /* The DOS header and stub */
6366 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6367 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6369 /* the dotnet header */
6370 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6372 /* the section tables */
6373 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6375 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6376 virtual_offset = VIRT_ALIGN;
6379 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6380 if (!assembly->sections [i].size)
6383 file_offset += FILE_ALIGN - 1;
6384 file_offset &= ~(FILE_ALIGN - 1);
6385 virtual_offset += VIRT_ALIGN - 1;
6386 virtual_offset &= ~(VIRT_ALIGN - 1);
6388 assembly->sections [i].offset = file_offset;
6389 assembly->sections [i].rva = virtual_offset;
6391 file_offset += assembly->sections [i].size;
6392 virtual_offset += assembly->sections [i].size;
6393 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6396 file_offset += FILE_ALIGN - 1;
6397 file_offset &= ~(FILE_ALIGN - 1);
6399 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6401 /* back-patch info */
6402 msdos = (MonoMSDOSHeader*)pefile->data;
6403 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6405 header = (MonoDotNetHeader*)(pefile->data + header_start);
6406 header->pesig [0] = 'P';
6407 header->pesig [1] = 'E';
6409 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6410 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6411 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6412 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6413 if (assemblyb->pekind == 1) {
6415 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6418 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6421 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6423 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6424 header->pe.pe_major = 6;
6425 header->pe.pe_minor = 0;
6426 size = assembly->sections [MONO_SECTION_TEXT].size;
6427 size += FILE_ALIGN - 1;
6428 size &= ~(FILE_ALIGN - 1);
6429 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6430 size = assembly->sections [MONO_SECTION_RSRC].size;
6431 size += FILE_ALIGN - 1;
6432 size &= ~(FILE_ALIGN - 1);
6433 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6434 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6435 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6436 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6437 /* pe_rva_entry_point always at the beginning of the text section */
6438 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6440 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6441 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6442 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6443 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6444 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6445 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6446 size = section_start;
6447 size += FILE_ALIGN - 1;
6448 size &= ~(FILE_ALIGN - 1);
6449 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6451 size += VIRT_ALIGN - 1;
6452 size &= ~(VIRT_ALIGN - 1);
6453 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6456 // Translate the PEFileKind value to the value expected by the Windows loader
6462 // PEFileKinds.Dll == 1
6463 // PEFileKinds.ConsoleApplication == 2
6464 // PEFileKinds.WindowApplication == 3
6467 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6468 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6470 if (assemblyb->pekind == 3)
6475 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6477 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6478 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6479 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6480 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6481 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6482 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6484 /* fill data directory entries */
6486 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6487 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6489 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6490 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6492 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6493 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6494 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6495 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6496 /* patch entrypoint name */
6497 if (assemblyb->pekind == 1)
6498 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6500 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6501 /* patch imported function RVA name */
6502 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6503 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6505 /* the import table */
6506 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6507 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6508 /* patch imported dll RVA name and other entries in the dir */
6509 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6510 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6511 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6512 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6513 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6514 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6516 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6517 value = (assembly->text_rva + assembly->imp_names_offset);
6518 *p++ = (value) & 0xff;
6519 *p++ = (value >> 8) & (0xff);
6520 *p++ = (value >> 16) & (0xff);
6521 *p++ = (value >> 24) & (0xff);
6523 /* the CLI header info */
6524 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6525 cli_header->ch_size = GUINT32_FROM_LE (72);
6526 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6527 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6528 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6529 if (assemblyb->entry_point) {
6530 guint32 table_idx = 0;
6531 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6532 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6533 table_idx = methodb->table_idx;
6535 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6537 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6539 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6541 /* The embedded managed resources */
6542 text_offset = assembly->text_rva + assembly->code.index;
6543 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6544 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6545 text_offset += assembly->resources.index;
6546 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6547 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6548 text_offset += assembly->meta_size;
6549 if (assembly->strong_name_size) {
6550 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6551 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6552 text_offset += assembly->strong_name_size;
6555 /* write the section tables and section content */
6556 section = (MonoSectionTable*)(pefile->data + section_start);
6557 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6558 static const char section_names [][7] = {
6559 ".text", ".rsrc", ".reloc"
6561 if (!assembly->sections [i].size)
6563 strcpy (section->st_name, section_names [i]);
6564 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6565 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6566 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6567 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6568 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6569 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6570 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6574 checked_write_file (file, pefile->data, pefile->index);
6576 mono_dynamic_stream_reset (pefile);
6578 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6579 if (!assembly->sections [i].size)
6582 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6583 g_error ("SetFilePointer returned %d\n", GetLastError ());
6586 case MONO_SECTION_TEXT:
6587 /* patch entry point */
6588 p = (guchar*)(assembly->code.data + 2);
6589 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6590 *p++ = (value) & 0xff;
6591 *p++ = (value >> 8) & 0xff;
6592 *p++ = (value >> 16) & 0xff;
6593 *p++ = (value >> 24) & 0xff;
6595 checked_write_file (file, assembly->code.data, assembly->code.index);
6596 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6597 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6598 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6601 g_free (assembly->image.raw_metadata);
6603 case MONO_SECTION_RELOC: {
6607 guint16 type_and_offset;
6611 g_assert (sizeof (reloc) == 12);
6613 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6614 reloc.block_size = GUINT32_FROM_LE (12);
6617 * the entrypoint is always at the start of the text section
6618 * 3 is IMAGE_REL_BASED_HIGHLOW
6619 * 2 is patch_size_rva - text_rva
6621 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6624 checked_write_file (file, &reloc, sizeof (reloc));
6628 case MONO_SECTION_RSRC:
6629 if (assembly->win32_res) {
6631 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6632 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6633 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6637 g_assert_not_reached ();
6641 /* check that the file is properly padded */
6642 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6643 g_error ("SetFilePointer returned %d\n", GetLastError ());
6644 if (! SetEndOfFile (file))
6645 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6647 mono_dynamic_stream_reset (&assembly->code);
6648 mono_dynamic_stream_reset (&assembly->us);
6649 mono_dynamic_stream_reset (&assembly->blob);
6650 mono_dynamic_stream_reset (&assembly->guid);
6651 mono_dynamic_stream_reset (&assembly->sheap);
6653 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6654 g_hash_table_destroy (assembly->blob_cache);
6655 assembly->blob_cache = NULL;
6660 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6663 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6665 g_assert_not_reached ();
6668 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6670 #ifndef DISABLE_REFLECTION_EMIT
6672 MonoReflectionModule *
6673 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6677 MonoImageOpenStatus status;
6678 MonoDynamicAssembly *assembly;
6679 guint32 module_count;
6680 MonoImage **new_modules;
6681 gboolean *new_modules_loaded;
6683 mono_error_init (error);
6685 name = mono_string_to_utf8 (fileName);
6687 image = mono_image_open (name, &status);
6689 if (status == MONO_IMAGE_ERROR_ERRNO)
6690 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6692 mono_error_set_bad_image_name (error, name, NULL);
6699 assembly = ab->dynamic_assembly;
6700 image->assembly = (MonoAssembly*)assembly;
6702 module_count = image->assembly->image->module_count;
6703 new_modules = g_new0 (MonoImage *, module_count + 1);
6704 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6706 if (image->assembly->image->modules)
6707 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6708 if (image->assembly->image->modules_loaded)
6709 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6710 new_modules [module_count] = image;
6711 new_modules_loaded [module_count] = TRUE;
6712 mono_image_addref (image);
6714 g_free (image->assembly->image->modules);
6715 image->assembly->image->modules = new_modules;
6716 image->assembly->image->modules_loaded = new_modules_loaded;
6717 image->assembly->image->module_count ++;
6719 mono_assembly_load_references (image, &status);
6721 mono_image_close (image);
6722 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6726 return mono_module_get_object_checked (mono_domain_get (), image, error);
6729 #endif /* DISABLE_REFLECTION_EMIT */
6732 * We need to return always the same object for MethodInfo, FieldInfo etc..
6733 * but we need to consider the reflected type.
6734 * type uses a different hash, since it uses custom hash/equal functions.
6739 MonoClass *refclass;
6743 reflected_equal (gconstpointer a, gconstpointer b) {
6744 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6745 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6747 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6751 reflected_hash (gconstpointer a) {
6752 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6753 return mono_aligned_addr_hash (ea->item);
6756 #define CHECK_OBJECT(t,p,k) \
6762 mono_domain_lock (domain); \
6763 if (!domain->refobject_hash) \
6764 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"); \
6765 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6766 mono_domain_unlock (domain); \
6769 mono_domain_unlock (domain); \
6772 #ifdef HAVE_BOEHM_GC
6773 /* ReflectedEntry doesn't need to be GC tracked */
6774 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6775 #define FREE_REFENTRY(entry) g_free ((entry))
6776 #define REFENTRY_REQUIRES_CLEANUP
6778 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6780 #define FREE_REFENTRY(entry)
6783 #define CACHE_OBJECT(t,p,o,k) \
6786 ReflectedEntry pe; \
6788 pe.refclass = (k); \
6789 mono_domain_lock (domain); \
6790 if (!domain->refobject_hash) \
6791 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"); \
6792 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6794 ReflectedEntry *e = ALLOC_REFENTRY; \
6796 e->refclass = (k); \
6797 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6800 mono_domain_unlock (domain); \
6805 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6807 mono_domain_lock (domain);
6808 if (domain->refobject_hash) {
6810 gpointer orig_pe, orig_value;
6813 pe.refclass = klass;
6814 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6815 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6816 FREE_REFENTRY (orig_pe);
6819 mono_domain_unlock (domain);
6822 #ifdef REFENTRY_REQUIRES_CLEANUP
6824 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6826 FREE_REFENTRY (key);
6831 mono_reflection_cleanup_domain (MonoDomain *domain)
6833 if (domain->refobject_hash) {
6834 /*let's avoid scanning the whole hashtable if not needed*/
6835 #ifdef REFENTRY_REQUIRES_CLEANUP
6836 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6838 mono_g_hash_table_destroy (domain->refobject_hash);
6839 domain->refobject_hash = NULL;
6843 #ifndef DISABLE_REFLECTION_EMIT
6845 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6847 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6851 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6853 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6857 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6859 MonoDynamicImage *image = moduleb->dynamic_image;
6860 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6864 MonoImage **new_modules;
6866 char *name, *fqname;
6868 * FIXME: we already created an image in mono_image_basic_init (), but
6869 * we don't know which module it belongs to, since that is only
6870 * determined at assembly save time.
6872 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6873 name = mono_string_to_utf8 (ab->name);
6874 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6875 if (!mono_error_ok (&error)) {
6877 mono_error_raise_exception (&error);
6879 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6881 moduleb->module.image = &image->image;
6882 moduleb->dynamic_image = image;
6883 register_module (mono_object_domain (moduleb), moduleb, image);
6885 /* register the module with the assembly */
6886 ass = ab->dynamic_assembly->assembly.image;
6887 module_count = ass->module_count;
6888 new_modules = g_new0 (MonoImage *, module_count + 1);
6891 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6892 new_modules [module_count] = &image->image;
6893 mono_image_addref (&image->image);
6895 g_free (ass->modules);
6896 ass->modules = new_modules;
6897 ass->module_count ++;
6902 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6904 MonoDynamicImage *image = moduleb->dynamic_image;
6906 g_assert (type->type);
6907 image->wrappers_type = mono_class_from_mono_type (type->type);
6913 * mono_assembly_get_object:
6914 * @domain: an app domain
6915 * @assembly: an assembly
6917 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6919 MonoReflectionAssembly*
6920 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6923 MonoReflectionAssembly *result;
6924 result = mono_assembly_get_object_checked (domain, assembly, &error);
6925 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6929 * mono_assembly_get_object_checked:
6930 * @domain: an app domain
6931 * @assembly: an assembly
6933 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6935 MonoReflectionAssembly*
6936 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6938 MonoReflectionAssembly *res;
6940 mono_error_init (error);
6942 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6943 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6946 res->assembly = assembly;
6948 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6953 MonoReflectionModule*
6954 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6957 MonoReflectionModule *result;
6958 result = mono_module_get_object_checked (domain, image, &error);
6959 mono_error_raise_exception (&error);
6963 MonoReflectionModule*
6964 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6966 MonoReflectionModule *res;
6969 mono_error_init (error);
6970 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6971 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6976 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6979 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6981 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6982 basename = g_path_get_basename (image->name);
6983 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6984 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6988 if (image->assembly->image == image) {
6989 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6993 if (image->assembly->image->modules) {
6994 for (i = 0; i < image->assembly->image->module_count; i++) {
6995 if (image->assembly->image->modules [i] == image)
6996 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6998 g_assert (res->token);
7002 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7005 MonoReflectionModule*
7006 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7009 MonoReflectionModule *result;
7010 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7011 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7015 MonoReflectionModule*
7016 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7018 MonoReflectionModule *res;
7019 MonoTableInfo *table;
7020 guint32 cols [MONO_FILE_SIZE];
7022 guint32 i, name_idx;
7025 mono_error_init (error);
7027 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7031 table = &image->tables [MONO_TABLE_FILE];
7032 g_assert (table_index < table->rows);
7033 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7036 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7039 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7040 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7042 /* Check whenever the row has a corresponding row in the moduleref table */
7043 table = &image->tables [MONO_TABLE_MODULEREF];
7044 for (i = 0; i < table->rows; ++i) {
7045 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7046 val = mono_metadata_string_heap (image, name_idx);
7047 if (strcmp (val, name) == 0)
7048 res->image = image->modules [i];
7051 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7052 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7053 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7054 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7055 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7061 verify_safe_for_managed_space (MonoType *type)
7063 switch (type->type) {
7065 case MONO_TYPE_ARRAY:
7066 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7068 return verify_safe_for_managed_space (type->data.type);
7069 case MONO_TYPE_SZARRAY:
7070 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7071 case MONO_TYPE_GENERICINST: {
7072 MonoGenericInst *inst = type->data.generic_class->inst;
7076 for (i = 0; i < inst->type_argc; ++i)
7077 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7083 case MONO_TYPE_MVAR:
7091 mono_type_normalize (MonoType *type)
7094 MonoGenericClass *gclass;
7095 MonoGenericInst *ginst;
7097 MonoGenericContainer *gcontainer;
7098 MonoType **argv = NULL;
7099 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7101 if (type->type != MONO_TYPE_GENERICINST)
7104 gclass = type->data.generic_class;
7105 ginst = gclass->context.class_inst;
7106 if (!ginst->is_open)
7109 gtd = gclass->container_class;
7110 gcontainer = gtd->generic_container;
7111 argv = g_newa (MonoType*, ginst->type_argc);
7113 for (i = 0; i < ginst->type_argc; ++i) {
7114 MonoType *t = ginst->type_argv [i], *norm;
7115 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7116 is_denorm_gtd = FALSE;
7117 norm = mono_type_normalize (t);
7120 requires_rebind = TRUE;
7124 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7126 if (requires_rebind) {
7127 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7128 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7134 * mono_type_get_object:
7135 * @domain: an app domain
7138 * Return an System.MonoType object representing the type @type.
7141 mono_type_get_object (MonoDomain *domain, MonoType *type)
7144 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7145 mono_error_raise_exception (&error);
7151 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7153 MonoType *norm_type;
7154 MonoReflectionType *res;
7157 mono_error_init (error);
7159 klass = mono_class_from_mono_type (type);
7161 /*we must avoid using @type as it might have come
7162 * from a mono_metadata_type_dup and the caller
7163 * expects that is can be freed.
7164 * Using the right type from
7166 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7168 /* void is very common */
7169 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7170 return (MonoReflectionType*)domain->typeof_void;
7173 * If the vtable of the given class was already created, we can use
7174 * the MonoType from there and avoid all locking and hash table lookups.
7176 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7177 * that the resulting object is different.
7179 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7180 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7181 if (vtable && vtable->type)
7182 return (MonoReflectionType *)vtable->type;
7185 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7186 mono_domain_lock (domain);
7187 if (!domain->type_hash)
7188 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7189 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7190 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7191 mono_domain_unlock (domain);
7192 mono_loader_unlock ();
7196 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7197 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7198 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7199 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7200 * artifact of how generics are encoded and should be transparent to managed code so we
7201 * need to weed out this diference when retrieving managed System.Type objects.
7203 norm_type = mono_type_normalize (type);
7204 if (norm_type != type) {
7205 res = mono_type_get_object_checked (domain, norm_type, error);
7206 if (!mono_error_ok (error))
7208 mono_g_hash_table_insert (domain->type_hash, type, res);
7209 mono_domain_unlock (domain);
7210 mono_loader_unlock ();
7214 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7215 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7218 if (!verify_safe_for_managed_space (type)) {
7219 mono_domain_unlock (domain);
7220 mono_loader_unlock ();
7221 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7225 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7226 gboolean is_type_done = TRUE;
7227 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7228 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7229 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7231 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7232 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7234 if (gparam->owner && gparam->owner->is_method) {
7235 MonoMethod *method = gparam->owner->owner.method;
7236 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7237 is_type_done = FALSE;
7238 } else if (gparam->owner && !gparam->owner->is_method) {
7239 MonoClass *klass = gparam->owner->owner.klass;
7240 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7241 is_type_done = FALSE;
7245 /* g_assert_not_reached (); */
7246 /* should this be considered an error condition? */
7247 if (is_type_done && !type->byref) {
7248 mono_domain_unlock (domain);
7249 mono_loader_unlock ();
7250 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7253 /* This is stored in vtables/JITted code so it has to be pinned */
7254 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7255 if (!mono_error_ok (error))
7259 mono_g_hash_table_insert (domain->type_hash, type, res);
7261 if (type->type == MONO_TYPE_VOID)
7262 domain->typeof_void = (MonoObject*)res;
7264 mono_domain_unlock (domain);
7265 mono_loader_unlock ();
7270 * mono_method_get_object:
7271 * @domain: an app domain
7273 * @refclass: the reflected type (can be NULL)
7275 * Return an System.Reflection.MonoMethod object representing the method @method.
7277 MonoReflectionMethod*
7278 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7281 MonoReflectionMethod *ret = NULL;
7282 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7283 mono_error_raise_exception (&error);
7288 * mono_method_get_object_checked:
7289 * @domain: an app domain
7291 * @refclass: the reflected type (can be NULL)
7292 * @error: set on error.
7294 * Return an System.Reflection.MonoMethod object representing the method @method.
7295 * Returns NULL and sets @error on error.
7297 MonoReflectionMethod*
7298 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7301 * We use the same C representation for methods and constructors, but the type
7302 * name in C# is different.
7304 MonoReflectionType *rt;
7306 MonoReflectionMethod *ret;
7308 mono_error_init (error);
7310 if (method->is_inflated) {
7311 MonoReflectionGenericMethod *gret;
7314 refclass = method->klass;
7315 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7316 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7317 klass = mono_class_get_mono_generic_cmethod_class ();
7319 klass = mono_class_get_mono_generic_method_class ();
7321 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7322 if (!mono_error_ok (error))
7324 gret->method.method = method;
7326 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7328 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7329 if (!mono_error_ok (error))
7332 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7334 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7338 refclass = method->klass;
7340 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7341 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7342 klass = mono_class_get_mono_cmethod_class ();
7345 klass = mono_class_get_mono_method_class ();
7347 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7348 if (!mono_error_ok (error))
7350 ret->method = method;
7352 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7353 if (!mono_error_ok (error))
7356 MONO_OBJECT_SETREF (ret, reftype, rt);
7358 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7361 g_assert (!mono_error_ok (error));
7366 * mono_method_clear_object:
7368 * Clear the cached reflection objects for the dynamic method METHOD.
7371 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7374 g_assert (method_is_dynamic (method));
7376 klass = method->klass;
7378 clear_cached_object (domain, method, klass);
7379 klass = klass->parent;
7381 /* Added by mono_param_get_objects () */
7382 clear_cached_object (domain, &(method->signature), NULL);
7383 klass = method->klass;
7385 clear_cached_object (domain, &(method->signature), klass);
7386 klass = klass->parent;
7391 * mono_field_get_object:
7392 * @domain: an app domain
7396 * Return an System.Reflection.MonoField object representing the field @field
7399 MonoReflectionField*
7400 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7403 MonoReflectionField *result;
7404 result = mono_field_get_object_checked (domain, klass, field, &error);
7405 mono_error_raise_exception (&error);
7410 * mono_field_get_object_checked:
7411 * @domain: an app domain
7414 * @error: set on error
7416 * Return an System.Reflection.MonoField object representing the field @field
7417 * in class @klass. On error, returns NULL and sets @error.
7419 MonoReflectionField*
7420 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7422 MonoReflectionType *rt;
7423 MonoReflectionField *res;
7425 mono_error_init (error);
7427 CHECK_OBJECT (MonoReflectionField *, field, klass);
7428 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7433 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7435 if (is_field_on_inst (field)) {
7436 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7438 rt = mono_type_get_object_checked (domain, field->type, error);
7439 if (!mono_error_ok (error))
7442 MONO_OBJECT_SETREF (res, type, rt);
7445 rt = mono_type_get_object_checked (domain, field->type, error);
7446 if (!mono_error_ok (error))
7449 MONO_OBJECT_SETREF (res, type, rt);
7451 res->attrs = mono_field_get_flags (field);
7453 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7457 * mono_property_get_object:
7458 * @domain: an app domain
7460 * @property: a property
7462 * Return an System.Reflection.MonoProperty object representing the property @property
7465 MonoReflectionProperty*
7466 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7469 MonoReflectionProperty *result;
7470 result = mono_property_get_object_checked (domain, klass, property, &error);
7471 mono_error_raise_exception (&error);
7476 * mono_property_get_object:
7477 * @domain: an app domain
7479 * @property: a property
7480 * @error: set on error
7482 * Return an System.Reflection.MonoProperty object representing the property @property
7483 * in class @klass. On error returns NULL and sets @error.
7485 MonoReflectionProperty*
7486 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7488 MonoReflectionProperty *res;
7490 mono_error_init (error);
7492 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7493 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7497 res->property = property;
7498 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7502 * mono_event_get_object:
7503 * @domain: an app domain
7507 * Return an System.Reflection.MonoEvent object representing the event @event
7510 MonoReflectionEvent*
7511 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7514 MonoReflectionEvent *result;
7515 result = mono_event_get_object_checked (domain, klass, event, &error);
7516 mono_error_raise_exception (&error);
7521 * mono_event_get_object_checked:
7522 * @domain: an app domain
7525 * @error: set on error
7527 * Return an System.Reflection.MonoEvent object representing the event @event
7528 * in class @klass. On failure sets @error and returns NULL
7530 MonoReflectionEvent*
7531 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7533 MonoReflectionEvent *res;
7534 MonoReflectionMonoEvent *mono_event;
7536 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7537 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7540 mono_event->klass = klass;
7541 mono_event->event = event;
7542 res = (MonoReflectionEvent*)mono_event;
7543 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7547 * mono_get_reflection_missing_object:
7548 * @domain: Domain where the object lives
7550 * Returns the System.Reflection.Missing.Value singleton object
7551 * (of type System.Reflection.Missing).
7553 * Used as the value for ParameterInfo.DefaultValue when Optional
7557 mono_get_reflection_missing_object (MonoDomain *domain)
7561 static MonoClassField *missing_value_field = NULL;
7563 if (!missing_value_field) {
7564 MonoClass *missing_klass;
7565 missing_klass = mono_class_get_missing_class ();
7566 mono_class_init (missing_klass);
7567 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7568 g_assert (missing_value_field);
7570 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7571 mono_error_assert_ok (&error);
7576 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7579 *dbnull = mono_get_dbnull_object (domain);
7584 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7586 if (!*reflection_missing)
7587 *reflection_missing = mono_get_reflection_missing_object (domain);
7588 return *reflection_missing;
7592 * mono_param_get_objects:
7593 * @domain: an app domain
7596 * Return an System.Reflection.ParameterInfo array object representing the parameters
7597 * in the method @method.
7600 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7602 static MonoClass *System_Reflection_ParameterInfo;
7603 static MonoClass *System_Reflection_ParameterInfo_array;
7604 MonoArray *res = NULL;
7605 MonoReflectionMethod *member = NULL;
7606 MonoReflectionParameter *param = NULL;
7607 char **names = NULL, **blobs = NULL;
7608 guint32 *types = NULL;
7609 MonoType *type = NULL;
7610 MonoObject *dbnull = NULL;
7611 MonoObject *missing = NULL;
7612 MonoMarshalSpec **mspecs = NULL;
7613 MonoMethodSignature *sig = NULL;
7614 MonoVTable *pinfo_vtable;
7615 MonoReflectionType *rt;
7618 mono_error_init (error);
7620 if (!System_Reflection_ParameterInfo_array) {
7623 klass = mono_class_get_mono_parameter_info_class ();
7625 mono_memory_barrier ();
7626 System_Reflection_ParameterInfo = klass;
7629 klass = mono_array_class_get (klass, 1);
7630 mono_memory_barrier ();
7631 System_Reflection_ParameterInfo_array = klass;
7634 sig = mono_method_signature_checked (method, error);
7635 if (!mono_error_ok (error))
7638 if (!sig->param_count) {
7639 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7646 /* Note: the cache is based on the address of the signature into the method
7647 * since we already cache MethodInfos with the method as keys.
7649 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7651 member = mono_method_get_object_checked (domain, method, refclass, error);
7654 names = g_new (char *, sig->param_count);
7655 mono_method_get_param_names (method, (const char **) names);
7657 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7658 mono_method_get_marshal_info (method, mspecs);
7660 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7664 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7665 for (i = 0; i < sig->param_count; ++i) {
7666 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7670 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7674 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7676 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7678 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7680 param->PositionImpl = i;
7681 param->AttrsImpl = sig->params [i]->attrs;
7683 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7684 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7685 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7687 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7691 blobs = g_new0 (char *, sig->param_count);
7692 types = g_new0 (guint32, sig->param_count);
7693 get_default_param_value_blobs (method, blobs, types);
7696 /* Build MonoType for the type from the Constant Table */
7698 type = g_new0 (MonoType, 1);
7699 type->type = (MonoTypeEnum)types [i];
7700 type->data.klass = NULL;
7701 if (types [i] == MONO_TYPE_CLASS)
7702 type->data.klass = mono_defaults.object_class;
7703 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7704 /* For enums, types [i] contains the base type */
7706 type->type = MONO_TYPE_VALUETYPE;
7707 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7709 type->data.klass = mono_class_from_mono_type (type);
7711 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7714 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7716 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7717 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7718 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7719 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7721 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7726 if (mspecs [i + 1]) {
7727 MonoReflectionMarshalAsAttribute* mobj;
7728 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7731 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7734 mono_array_setref (res, i, param);
7744 for (i = sig->param_count; i >= 0; i--) {
7746 mono_metadata_free_marshal_spec (mspecs [i]);
7754 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7758 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7761 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7762 mono_error_assert_ok (&error);
7767 * mono_method_body_get_object:
7768 * @domain: an app domain
7771 * Return an System.Reflection.MethodBody object representing the method @method.
7773 MonoReflectionMethodBody*
7774 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7777 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7778 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7783 * mono_method_body_get_object_checked:
7784 * @domain: an app domain
7786 * @error: set on error
7788 * Return an System.Reflection.MethodBody object representing the
7789 * method @method. On failure, returns NULL and sets @error.
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7794 MonoReflectionMethodBody *ret;
7795 MonoMethodHeader *header;
7797 MonoReflectionType *rt;
7798 guint32 method_rva, local_var_sig_token;
7800 unsigned char format, flags;
7803 mono_error_init (error);
7805 /* for compatibility with .net */
7806 if (method_is_dynamic (method)) {
7807 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7811 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7813 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7814 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7815 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7816 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7817 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7820 image = method->klass->image;
7821 header = mono_method_get_header_checked (method, error);
7822 return_val_if_nok (error, NULL);
7824 if (!image_is_dynamic (image)) {
7825 /* Obtain local vars signature token */
7826 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7827 ptr = mono_image_rva_map (image, method_rva);
7828 flags = *(const unsigned char *) ptr;
7829 format = flags & METHOD_HEADER_FORMAT_MASK;
7831 case METHOD_HEADER_TINY_FORMAT:
7832 local_var_sig_token = 0;
7834 case METHOD_HEADER_FAT_FORMAT:
7838 local_var_sig_token = read32 (ptr);
7841 g_assert_not_reached ();
7844 local_var_sig_token = 0; //FIXME
7846 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7850 ret->init_locals = header->init_locals;
7851 ret->max_stack = header->max_stack;
7852 ret->local_var_sig_token = local_var_sig_token;
7853 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7854 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7857 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7858 for (i = 0; i < header->num_locals; ++i) {
7859 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7863 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7867 MONO_OBJECT_SETREF (info, local_type, rt);
7869 info->is_pinned = header->locals [i]->pinned;
7870 info->local_index = i;
7871 mono_array_setref (ret->locals, i, info);
7875 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7876 for (i = 0; i < header->num_clauses; ++i) {
7877 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7880 MonoExceptionClause *clause = &header->clauses [i];
7882 info->flags = clause->flags;
7883 info->try_offset = clause->try_offset;
7884 info->try_length = clause->try_len;
7885 info->handler_offset = clause->handler_offset;
7886 info->handler_length = clause->handler_len;
7887 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7888 info->filter_offset = clause->data.filter_offset;
7889 else if (clause->data.catch_class) {
7890 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7894 MONO_OBJECT_SETREF (info, catch_type, rt);
7897 mono_array_setref (ret->clauses, i, info);
7900 mono_metadata_free_mh (header);
7901 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7905 mono_metadata_free_mh (header);
7910 * mono_get_dbnull_object:
7911 * @domain: Domain where the object lives
7913 * Returns the System.DBNull.Value singleton object
7915 * Used as the value for ParameterInfo.DefaultValue
7918 mono_get_dbnull_object (MonoDomain *domain)
7922 static MonoClassField *dbnull_value_field = NULL;
7924 if (!dbnull_value_field) {
7925 MonoClass *dbnull_klass;
7926 dbnull_klass = mono_class_get_dbnull_class ();
7927 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7928 g_assert (dbnull_value_field);
7930 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7931 mono_error_assert_ok (&error);
7936 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7938 guint32 param_index, i, lastp, crow = 0;
7939 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7942 MonoClass *klass = method->klass;
7943 MonoImage *image = klass->image;
7944 MonoMethodSignature *methodsig = mono_method_signature (method);
7946 MonoTableInfo *constt;
7947 MonoTableInfo *methodt;
7948 MonoTableInfo *paramt;
7950 if (!methodsig->param_count)
7953 mono_class_init (klass);
7955 if (image_is_dynamic (klass->image)) {
7956 MonoReflectionMethodAux *aux;
7957 if (method->is_inflated)
7958 method = ((MonoMethodInflated*)method)->declaring;
7959 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7960 if (aux && aux->param_defaults) {
7961 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7962 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7967 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7968 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7969 constt = &image->tables [MONO_TABLE_CONSTANT];
7971 idx = mono_method_get_index (method) - 1;
7972 g_assert (idx != -1);
7974 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7975 if (idx + 1 < methodt->rows)
7976 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7978 lastp = paramt->rows + 1;
7980 for (i = param_index; i < lastp; ++i) {
7983 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7984 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7986 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7989 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7994 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7995 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7996 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8003 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8008 MonoType *basetype = type;
8010 mono_error_init (error);
8015 klass = mono_class_from_mono_type (type);
8016 if (klass->valuetype) {
8017 object = mono_object_new_checked (domain, klass, error);
8018 return_val_if_nok (error, NULL);
8019 retval = ((gchar *) object + sizeof (MonoObject));
8020 if (klass->enumtype)
8021 basetype = mono_class_enum_basetype (klass);
8026 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
8033 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8036 gboolean quoted = FALSE;
8038 memset (assembly, 0, sizeof (MonoAssemblyName));
8039 assembly->culture = "";
8040 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8047 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8058 /* Remove trailing whitespace */
8060 while (*s && g_ascii_isspace (*s))
8063 while (g_ascii_isspace (*p))
8066 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8068 assembly->major = strtoul (p, &s, 10);
8069 if (s == p || *s != '.')
8072 assembly->minor = strtoul (p, &s, 10);
8073 if (s == p || *s != '.')
8076 assembly->build = strtoul (p, &s, 10);
8077 if (s == p || *s != '.')
8080 assembly->revision = strtoul (p, &s, 10);
8084 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8086 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8087 assembly->culture = "";
8090 assembly->culture = p;
8091 while (*p && *p != ',') {
8095 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8097 if (strncmp (p, "null", 4) == 0) {
8102 while (*p && *p != ',') {
8105 len = (p - start + 1);
8106 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8107 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8108 g_strlcpy ((char*)assembly->public_key_token, start, len);
8111 while (*p && *p != ',')
8115 while (g_ascii_isspace (*p) || *p == ',') {
8129 * mono_reflection_parse_type:
8132 * Parse a type name as accepted by the GetType () method and output the info
8133 * extracted in the info structure.
8134 * the name param will be mangled, so, make a copy before passing it to this function.
8135 * The fields in info will be valid until the memory pointed to by name is valid.
8137 * See also mono_type_get_name () below.
8139 * Returns: 0 on parse error.
8142 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8143 MonoTypeNameParse *info)
8145 char *start, *p, *w, *last_point, *startn;
8146 int in_modifiers = 0;
8147 int isbyref = 0, rank = 0, isptr = 0;
8149 start = p = w = name;
8151 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8152 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8153 info->name = info->name_space = NULL;
8154 info->nested = NULL;
8155 info->modifiers = NULL;
8156 info->type_arguments = NULL;
8158 /* last_point separates the namespace from the name */
8161 while (*p == ' ') p++, start++, w++, name++;
8166 *p = 0; /* NULL terminate the name */
8168 info->nested = g_list_append (info->nested, startn);
8169 /* we have parsed the nesting namespace + name */
8173 info->name_space = start;
8175 info->name = last_point + 1;
8177 info->name_space = (char *)"";
8205 info->name_space = start;
8207 info->name = last_point + 1;
8209 info->name_space = (char *)"";
8216 if (isbyref) /* only one level allowed by the spec */
8220 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8224 if (isbyref) /* pointer to ref not okay */
8226 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8231 if (isbyref) /* array of ref and generic ref are not okay */
8233 //Decide if it's an array of a generic argument list
8238 if (*p == ',' || *p == '*' || *p == ']') { //array
8246 else if (*p == '*') /* '*' means unknown lower bound */
8247 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8254 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8256 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8259 info->type_arguments = g_ptr_array_new ();
8261 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8262 gboolean fqname = FALSE;
8264 g_ptr_array_add (info->type_arguments, subinfo);
8266 while (*p == ' ') p++;
8272 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8275 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8276 if (fqname && (*p != ']')) {
8284 while (*p && (*p != ']'))
8292 if (g_ascii_isspace (*aname)) {
8299 !assembly_name_to_aname (&subinfo->assembly, aname))
8301 } else if (fqname && (*p == ']')) {
8323 if (g_ascii_isspace (*p)) {
8330 return 0; /* missing assembly name */
8331 if (!assembly_name_to_aname (&info->assembly, p))
8337 if (info->assembly.name)
8340 // *w = 0; /* terminate class name */
8342 if (!info->name || !*info->name)
8346 /* add other consistency checks */
8352 * mono_identifier_unescape_type_name_chars:
8353 * @identifier: the display name of a mono type
8356 * The name in internal form, that is without escaping backslashes.
8358 * The string is modified in place!
8361 mono_identifier_unescape_type_name_chars(char* identifier)
8366 for (w = r = identifier; *r != 0; r++)
8384 mono_identifier_unescape_info (MonoTypeNameParse* info);
8387 unescape_each_type_argument(void* data, void* user_data)
8389 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8390 mono_identifier_unescape_info (info);
8394 unescape_each_nested_name (void* data, void* user_data)
8396 char* nested_name = (char*) data;
8397 mono_identifier_unescape_type_name_chars(nested_name);
8401 * mono_identifier_unescape_info:
8403 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8407 * Destructively updates the info by unescaping the identifiers that
8408 * comprise the type namespace, name, nested types (if any) and
8409 * generic type arguments (if any).
8411 * The resulting info has the names in internal form.
8415 mono_identifier_unescape_info (MonoTypeNameParse *info)
8419 mono_identifier_unescape_type_name_chars(info->name_space);
8420 mono_identifier_unescape_type_name_chars(info->name);
8421 // but don't escape info->assembly
8422 if (info->type_arguments)
8423 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8425 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8429 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8431 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8433 mono_identifier_unescape_info (info);
8439 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8441 gboolean type_resolve = FALSE;
8443 MonoImage *rootimage = image;
8445 mono_error_init (error);
8447 if (info->assembly.name) {
8448 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8449 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8451 * This could happen in the AOT compiler case when the search hook is not
8454 assembly = image->assembly;
8456 /* then we must load the assembly ourselve - see #60439 */
8457 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8461 image = assembly->image;
8462 } else if (!image) {
8463 image = mono_defaults.corlib;
8466 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8467 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8468 mono_error_cleanup (error);
8469 image = mono_defaults.corlib;
8470 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8477 * mono_reflection_get_type_internal:
8479 * Returns: may return NULL on success, sets error on failure.
8482 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8487 gboolean bounded = FALSE;
8489 mono_error_init (error);
8491 image = mono_defaults.corlib;
8494 rootimage = mono_defaults.corlib;
8497 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8499 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8504 for (mod = info->nested; mod; mod = mod->next) {
8505 gpointer iter = NULL;
8509 mono_class_init (parent);
8511 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8513 char *nested_name, *nested_nspace;
8514 gboolean match = TRUE;
8516 lastp = strrchr ((const char *)mod->data, '.');
8518 /* Nested classes can have namespaces */
8521 nested_name = g_strdup (lastp + 1);
8522 nspace_len = lastp - (char*)mod->data;
8523 nested_nspace = (char *)g_malloc (nspace_len + 1);
8524 memcpy (nested_nspace, mod->data, nspace_len);
8525 nested_nspace [nspace_len] = '\0';
8528 nested_name = (char *)mod->data;
8529 nested_nspace = NULL;
8532 if (nested_nspace) {
8534 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8537 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8543 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8546 if (strcmp (klass->name, nested_name) != 0)
8551 g_free (nested_name);
8552 g_free (nested_nspace);
8564 if (info->type_arguments) {
8565 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8566 MonoReflectionType *the_type;
8570 for (i = 0; i < info->type_arguments->len; i++) {
8571 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8573 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8574 if (!type_args [i]) {
8580 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8584 instance = mono_reflection_bind_generic_parameters (
8585 the_type, info->type_arguments->len, type_args, error);
8591 klass = mono_class_from_mono_type (instance);
8594 for (mod = info->modifiers; mod; mod = mod->next) {
8595 modval = GPOINTER_TO_UINT (mod->data);
8596 if (!modval) { /* byref: must be last modifier */
8597 return &klass->this_arg;
8598 } else if (modval == -1) {
8599 klass = mono_ptr_class_get (&klass->byval_arg);
8600 } else if (modval == -2) {
8602 } else { /* array rank */
8603 klass = mono_bounded_array_class_get (klass, modval, bounded);
8607 return &klass->byval_arg;
8611 * mono_reflection_get_type:
8612 * @image: a metadata context
8613 * @info: type description structure
8614 * @ignorecase: flag for case-insensitive string compares
8615 * @type_resolve: whenever type resolve was already tried
8617 * Build a MonoType from the type description in @info.
8622 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8624 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8625 mono_error_cleanup (&error);
8630 * mono_reflection_get_type_checked:
8631 * @image: a metadata context
8632 * @info: type description structure
8633 * @ignorecase: flag for case-insensitive string compares
8634 * @type_resolve: whenever type resolve was already tried
8635 * @error: set on error.
8637 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8641 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8642 mono_error_init (error);
8643 return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8648 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8650 MonoReflectionAssemblyBuilder *abuilder;
8654 mono_error_init (error);
8655 g_assert (assembly_is_dynamic (assembly));
8656 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8660 /* Enumerate all modules */
8663 if (abuilder->modules) {
8664 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8665 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8666 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8669 if (!mono_error_ok (error))
8674 if (!type && abuilder->loaded_modules) {
8675 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8676 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8677 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8680 if (!mono_error_ok (error))
8689 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8692 MonoReflectionAssembly *assembly;
8696 mono_error_init (error);
8698 if (image && image_is_dynamic (image))
8699 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8701 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8703 return_val_if_nok (error, NULL);
8707 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8714 *type_resolve = TRUE;
8717 /* Reconstruct the type name */
8718 fullName = g_string_new ("");
8719 if (info->name_space && (info->name_space [0] != '\0'))
8720 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8722 g_string_printf (fullName, "%s", info->name);
8723 for (mod = info->nested; mod; mod = mod->next)
8724 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8726 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8727 if (!is_ok (error)) {
8728 g_string_free (fullName, TRUE);
8733 if (assembly_is_dynamic (assembly->assembly))
8734 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8735 info, ignorecase, error);
8737 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8738 info, ignorecase, error);
8740 g_string_free (fullName, TRUE);
8741 return_val_if_nok (error, NULL);
8746 mono_reflection_free_type_info (MonoTypeNameParse *info)
8748 g_list_free (info->modifiers);
8749 g_list_free (info->nested);
8751 if (info->type_arguments) {
8754 for (i = 0; i < info->type_arguments->len; i++) {
8755 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8757 mono_reflection_free_type_info (subinfo);
8758 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8762 g_ptr_array_free (info->type_arguments, TRUE);
8767 * mono_reflection_type_from_name:
8769 * @image: a metadata context (can be NULL).
8771 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8772 * it defaults to get the type from @image or, if @image is NULL or loading
8773 * from it fails, uses corlib.
8777 mono_reflection_type_from_name (char *name, MonoImage *image)
8780 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8781 mono_error_cleanup (&error);
8786 * mono_reflection_type_from_name_checked:
8788 * @image: a metadata context (can be NULL).
8789 * @error: set on errror.
8791 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8792 * it defaults to get the type from @image or, if @image is NULL or loading
8793 * from it fails, uses corlib. On failure returns NULL and sets @error.
8797 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8799 MonoType *type = NULL;
8800 MonoTypeNameParse info;
8803 mono_error_init (error);
8804 /* Make a copy since parse_type modifies its argument */
8805 tmp = g_strdup (name);
8807 /*g_print ("requested type %s\n", str);*/
8808 if (mono_reflection_parse_type (tmp, &info)) {
8809 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8810 if (!is_ok (error)) {
8812 mono_reflection_free_type_info (&info);
8818 mono_reflection_free_type_info (&info);
8823 * mono_reflection_get_token:
8825 * Return the metadata token of OBJ which should be an object
8826 * representing a metadata element.
8829 mono_reflection_get_token (MonoObject *obj)
8832 guint32 result = mono_reflection_get_token_checked (obj, &error);
8833 mono_error_assert_ok (&error);
8838 * mono_reflection_get_token_checked:
8840 * @error: set on error
8842 * Return the metadata token of @obj which should be an object
8843 * representing a metadata element. On failure sets @error.
8846 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8851 mono_error_init (error);
8853 klass = obj->vtable->klass;
8855 if (strcmp (klass->name, "MethodBuilder") == 0) {
8856 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8858 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8859 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8860 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8862 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8863 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8864 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8866 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8867 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8868 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8869 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8870 } else if (strcmp (klass->name, "MonoType") == 0) {
8871 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8872 return_val_if_nok (error, 0);
8873 MonoClass *mc = mono_class_from_mono_type (type);
8874 if (!mono_class_init (mc)) {
8875 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8879 token = mc->type_token;
8880 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8881 strcmp (klass->name, "MonoMethod") == 0 ||
8882 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8883 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8884 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8885 if (m->method->is_inflated) {
8886 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8887 return inflated->declaring->token;
8889 token = m->method->token;
8891 } else if (strcmp (klass->name, "MonoField") == 0) {
8892 MonoReflectionField *f = (MonoReflectionField*)obj;
8894 if (is_field_on_inst (f->field)) {
8895 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8897 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8898 int field_index = f->field - dgclass->fields;
8901 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8902 obj = dgclass->field_objects [field_index];
8903 return mono_reflection_get_token_checked (obj, error);
8906 token = mono_class_get_field_token (f->field);
8907 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8908 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8910 token = mono_class_get_property_token (p->property);
8911 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8912 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8914 token = mono_class_get_event_token (p->event);
8915 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8916 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8917 MonoClass *member_class = mono_object_class (p->MemberImpl);
8918 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8920 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8921 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8922 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8925 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8926 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8928 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8929 klass->name_space, klass->name);
8937 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8941 int slen = mono_metadata_decode_value (p, &p);
8943 mono_error_init (error);
8945 n = (char *)g_memdup (p, slen + 1);
8947 t = mono_reflection_type_from_name_checked (n, image, error);
8949 char *msg = g_strdup (mono_error_get_message (error));
8950 mono_error_cleanup (error);
8951 /* We don't free n, it's consumed by mono_error */
8952 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8959 return mono_class_from_mono_type (t);
8963 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8965 int slen, type = t->type;
8966 MonoClass *tklass = t->data.klass;
8968 mono_error_init (error);
8974 case MONO_TYPE_BOOLEAN: {
8975 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8980 case MONO_TYPE_CHAR:
8982 case MONO_TYPE_I2: {
8983 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8988 #if SIZEOF_VOID_P == 4
8994 case MONO_TYPE_I4: {
8995 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9000 #if SIZEOF_VOID_P == 8
9001 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9005 case MONO_TYPE_I8: {
9006 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9011 case MONO_TYPE_R8: {
9012 double *val = (double *)g_malloc (sizeof (double));
9017 case MONO_TYPE_VALUETYPE:
9018 if (t->data.klass->enumtype) {
9019 type = mono_class_enum_basetype (t->data.klass)->type;
9022 MonoClass *k = t->data.klass;
9024 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9025 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9031 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9034 case MONO_TYPE_STRING:
9035 if (*p == (char)0xFF) {
9039 slen = mono_metadata_decode_value (p, &p);
9041 return mono_string_new_len (mono_domain_get (), p, slen);
9042 case MONO_TYPE_CLASS: {
9043 MonoReflectionType *rt;
9046 if (*p == (char)0xFF) {
9051 slen = mono_metadata_decode_value (p, &p);
9052 n = (char *)g_memdup (p, slen + 1);
9054 t = mono_reflection_type_from_name_checked (n, image, error);
9056 char *msg = g_strdup (mono_error_get_message (error));
9057 mono_error_cleanup (error);
9058 /* We don't free n, it's consumed by mono_error */
9059 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9066 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9067 if (!mono_error_ok (error))
9072 case MONO_TYPE_OBJECT: {
9075 MonoClass *subc = NULL;
9080 } else if (subt == 0x0E) {
9081 type = MONO_TYPE_STRING;
9083 } else if (subt == 0x1D) {
9084 MonoType simple_type = {{0}};
9088 type = MONO_TYPE_SZARRAY;
9089 if (etype == 0x50) {
9090 tklass = mono_defaults.systemtype_class;
9091 } else if (etype == 0x55) {
9092 tklass = load_cattr_enum_type (image, p, &p, error);
9093 if (!mono_error_ok (error))
9097 /* See Partition II, Appendix B3 */
9098 etype = MONO_TYPE_OBJECT;
9099 simple_type.type = (MonoTypeEnum)etype;
9100 tklass = mono_class_from_mono_type (&simple_type);
9103 } else if (subt == 0x55) {
9106 slen = mono_metadata_decode_value (p, &p);
9107 n = (char *)g_memdup (p, slen + 1);
9109 t = mono_reflection_type_from_name_checked (n, image, error);
9111 char *msg = g_strdup (mono_error_get_message (error));
9112 mono_error_cleanup (error);
9113 /* We don't free n, it's consumed by mono_error */
9114 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9120 subc = mono_class_from_mono_type (t);
9121 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9122 MonoType simple_type = {{0}};
9123 simple_type.type = (MonoTypeEnum)subt;
9124 subc = mono_class_from_mono_type (&simple_type);
9126 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9128 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9130 if (mono_error_ok (error)) {
9131 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9132 g_assert (!subc->has_references);
9133 if (mono_error_ok (error))
9134 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9140 case MONO_TYPE_SZARRAY: {
9142 guint32 i, alen, basetype;
9145 if (alen == 0xffffffff) {
9149 arr = mono_array_new (mono_domain_get(), tklass, alen);
9150 basetype = tklass->byval_arg.type;
9151 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9152 basetype = mono_class_enum_basetype (tklass)->type;
9157 case MONO_TYPE_BOOLEAN:
9158 for (i = 0; i < alen; i++) {
9159 MonoBoolean val = *p++;
9160 mono_array_set (arr, MonoBoolean, i, val);
9163 case MONO_TYPE_CHAR:
9166 for (i = 0; i < alen; i++) {
9167 guint16 val = read16 (p);
9168 mono_array_set (arr, guint16, i, val);
9175 for (i = 0; i < alen; i++) {
9176 guint32 val = read32 (p);
9177 mono_array_set (arr, guint32, i, val);
9182 for (i = 0; i < alen; i++) {
9185 mono_array_set (arr, double, i, val);
9191 for (i = 0; i < alen; i++) {
9192 guint64 val = read64 (p);
9193 mono_array_set (arr, guint64, i, val);
9197 case MONO_TYPE_CLASS:
9198 case MONO_TYPE_OBJECT:
9199 case MONO_TYPE_STRING:
9200 case MONO_TYPE_SZARRAY:
9201 for (i = 0; i < alen; i++) {
9202 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9203 if (!mono_error_ok (error))
9205 mono_array_setref (arr, i, item);
9209 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9215 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9221 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9223 mono_error_init (error);
9225 gboolean is_ref = type_is_reference (t);
9227 void *val = load_cattr_value (image, t, p, end, error);
9228 if (!is_ok (error)) {
9235 return (MonoObject*)val;
9237 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9243 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9245 static MonoMethod *ctor;
9247 void *params [2], *unboxed;
9249 mono_error_init (error);
9252 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9254 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9255 return_val_if_nok (error, NULL);
9258 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9259 return_val_if_nok (error, NULL);
9260 unboxed = mono_object_unbox (retval);
9262 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9263 return_val_if_nok (error, NULL);
9269 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9271 static MonoMethod *ctor;
9273 void *unboxed, *params [2];
9275 mono_error_init (error);
9278 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9281 params [1] = typedarg;
9282 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9283 return_val_if_nok (error, NULL);
9285 unboxed = mono_object_unbox (retval);
9287 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9288 return_val_if_nok (error, NULL);
9294 type_is_reference (MonoType *type)
9296 switch (type->type) {
9297 case MONO_TYPE_BOOLEAN:
9298 case MONO_TYPE_CHAR:
9311 case MONO_TYPE_VALUETYPE:
9319 free_param_data (MonoMethodSignature *sig, void **params) {
9321 for (i = 0; i < sig->param_count; ++i) {
9322 if (!type_is_reference (sig->params [i]))
9323 g_free (params [i]);
9328 * Find the field index in the metadata FieldDef table.
9331 find_field_index (MonoClass *klass, MonoClassField *field) {
9334 for (i = 0; i < klass->field.count; ++i) {
9335 if (field == &klass->fields [i])
9336 return klass->field.first + 1 + i;
9342 * Find the property index in the metadata Property table.
9345 find_property_index (MonoClass *klass, MonoProperty *property) {
9348 for (i = 0; i < klass->ext->property.count; ++i) {
9349 if (property == &klass->ext->properties [i])
9350 return klass->ext->property.first + 1 + i;
9356 * Find the event index in the metadata Event table.
9359 find_event_index (MonoClass *klass, MonoEvent *event) {
9362 for (i = 0; i < klass->ext->event.count; ++i) {
9363 if (event == &klass->ext->events [i])
9364 return klass->ext->event.first + 1 + i;
9370 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9372 const char *p = (const char*)data;
9374 guint32 i, j, num_named;
9376 void *params_buf [32];
9377 void **params = NULL;
9378 MonoMethodSignature *sig;
9379 MonoObject *exc = NULL;
9381 mono_error_init (error);
9383 mono_class_init (method->klass);
9385 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9386 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9391 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9392 if (!mono_error_ok (error)) return NULL;
9394 mono_runtime_invoke_checked (method, attr, NULL, error);
9395 if (!mono_error_ok (error))
9401 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9404 /*g_print ("got attr %s\n", method->klass->name);*/
9406 sig = mono_method_signature (method);
9407 if (sig->param_count < 32) {
9408 params = params_buf;
9409 memset (params, 0, sizeof (void*) * sig->param_count);
9411 /* Allocate using GC so it gets GC tracking */
9412 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9417 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9418 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9419 if (!mono_error_ok (error))
9424 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9425 if (!mono_error_ok (error)) goto fail;
9427 mono_runtime_try_invoke (method, attr, params, &exc, error);
9428 if (!mono_error_ok (error))
9433 num_named = read16 (named);
9435 for (j = 0; j < num_named; j++) {
9437 char *name, named_type, data_type;
9438 named_type = *named++;
9439 data_type = *named++; /* type of data */
9440 if (data_type == MONO_TYPE_SZARRAY)
9441 data_type = *named++;
9442 if (data_type == MONO_TYPE_ENUM) {
9445 type_len = mono_metadata_decode_blob_size (named, &named);
9446 type_name = (char *)g_malloc (type_len + 1);
9447 memcpy (type_name, named, type_len);
9448 type_name [type_len] = 0;
9450 /* FIXME: lookup the type and check type consistency */
9453 name_len = mono_metadata_decode_blob_size (named, &named);
9454 name = (char *)g_malloc (name_len + 1);
9455 memcpy (name, named, name_len);
9456 name [name_len] = 0;
9458 if (named_type == 0x53) {
9459 MonoClassField *field;
9462 /* how this fail is a blackbox */
9463 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9465 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9470 val = load_cattr_value (image, field->type, named, &named, error);
9471 if (!mono_error_ok (error)) {
9473 if (!type_is_reference (field->type))
9478 mono_field_set_value (attr, field, val);
9479 if (!type_is_reference (field->type))
9481 } else if (named_type == 0x54) {
9484 MonoType *prop_type;
9486 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9489 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9495 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9500 /* can we have more that 1 arg in a custom attr named property? */
9501 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9502 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9504 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9505 if (!mono_error_ok (error)) {
9507 if (!type_is_reference (prop_type))
9508 g_free (pparams [0]);
9513 mono_property_set_value (prop, attr, pparams, NULL);
9514 if (!type_is_reference (prop_type))
9515 g_free (pparams [0]);
9520 free_param_data (method->signature, params);
9521 if (params != params_buf)
9522 mono_gc_free_fixed (params);
9527 free_param_data (method->signature, params);
9528 if (params != params_buf)
9529 mono_gc_free_fixed (params);
9531 mono_raise_exception ((MonoException*)exc);
9536 * mono_reflection_create_custom_attr_data_args:
9538 * Create an array of typed and named arguments from the cattr blob given by DATA.
9539 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9540 * NAMED_ARG_INFO will contain information about the named arguments.
9543 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)
9545 MonoArray *typedargs, *namedargs;
9546 MonoClass *attrklass;
9548 const char *p = (const char*)data;
9550 guint32 i, j, num_named;
9551 CattrNamedArg *arginfo = NULL;
9555 *named_arg_info = NULL;
9557 mono_error_init (error);
9559 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9560 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9564 mono_class_init (method->klass);
9566 domain = mono_domain_get ();
9568 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9571 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9575 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9578 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9579 return_if_nok (error);
9580 mono_array_setref (typedargs, i, obj);
9584 num_named = read16 (named);
9585 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9587 attrklass = method->klass;
9589 arginfo = g_new0 (CattrNamedArg, num_named);
9590 *named_arg_info = arginfo;
9592 for (j = 0; j < num_named; j++) {
9594 char *name, named_type, data_type;
9595 named_type = *named++;
9596 data_type = *named++; /* type of data */
9597 if (data_type == MONO_TYPE_SZARRAY)
9598 data_type = *named++;
9599 if (data_type == MONO_TYPE_ENUM) {
9602 type_len = mono_metadata_decode_blob_size (named, &named);
9603 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9606 type_name = (char *)g_malloc (type_len + 1);
9607 memcpy (type_name, named, type_len);
9608 type_name [type_len] = 0;
9610 /* FIXME: lookup the type and check type consistency */
9613 name_len = mono_metadata_decode_blob_size (named, &named);
9614 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9616 name = (char *)g_malloc (name_len + 1);
9617 memcpy (name, named, name_len);
9618 name [name_len] = 0;
9620 if (named_type == 0x53) {
9622 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9629 arginfo [j].type = field->type;
9630 arginfo [j].field = field;
9632 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9633 if (!is_ok (error)) {
9637 mono_array_setref (namedargs, j, obj);
9639 } else if (named_type == 0x54) {
9641 MonoType *prop_type;
9642 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9644 if (!prop || !prop->set) {
9649 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9650 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9652 arginfo [j].type = prop_type;
9653 arginfo [j].prop = prop;
9655 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9656 if (!is_ok (error)) {
9660 mono_array_setref (namedargs, j, obj);
9665 *typed_args = typedargs;
9666 *named_args = namedargs;
9669 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9671 *named_arg_info = NULL;
9675 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9678 MonoArray *typedargs, *namedargs;
9681 CattrNamedArg *arginfo = NULL;
9685 mono_error_init (&error);
9693 image = assembly->assembly->image;
9694 method = ref_method->method;
9695 domain = mono_object_domain (ref_method);
9697 if (!mono_class_init (method->klass))
9698 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9700 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9701 if (!mono_error_ok (&error))
9704 if (mono_loader_get_last_error ()) {
9705 mono_error_set_from_loader_error (&error);
9709 if (!typedargs || !namedargs)
9712 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9713 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9714 MonoObject *typedarg;
9716 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9717 if (!is_ok (&error))
9719 mono_array_setref (typedargs, i, typedarg);
9722 for (i = 0; i < mono_array_length (namedargs); ++i) {
9723 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9724 MonoObject *typedarg, *namedarg, *minfo;
9726 if (arginfo [i].prop) {
9727 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9731 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9732 if (!mono_error_ok (&error))
9736 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9737 if (!is_ok (&error))
9739 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9740 if (!is_ok (&error))
9743 mono_array_setref (namedargs, i, namedarg);
9746 *ctor_args = typedargs;
9747 *named_args = namedargs;
9750 mono_error_raise_exception (&error);
9755 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9757 static MonoMethod *ctor;
9763 mono_error_init (error);
9765 g_assert (image->assembly);
9768 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9770 domain = mono_domain_get ();
9771 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9772 return_val_if_nok (error, NULL);
9773 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9774 return_val_if_nok (error, NULL);
9775 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9776 return_val_if_nok (error, NULL);
9777 params [2] = (gpointer)&cattr->data;
9778 params [3] = &cattr->data_size;
9780 mono_runtime_invoke_checked (ctor, attr, params, error);
9781 return_val_if_nok (error, NULL);
9786 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9792 mono_error_init (error);
9795 for (i = 0; i < cinfo->num_attrs; ++i) {
9796 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9800 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9802 for (i = 0; i < cinfo->num_attrs; ++i) {
9803 if (!cinfo->attrs [i].ctor) {
9804 /* The cattr type is not finished yet */
9805 /* We should include the type name but cinfo doesn't contain it */
9806 mono_error_set_type_load_name (error, NULL, NULL, "");
9809 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9810 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9811 if (!mono_error_ok (error))
9813 mono_array_setref (result, n, attr);
9821 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9824 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9825 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9831 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9837 mono_error_init (error);
9838 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9839 for (i = 0; i < cinfo->num_attrs; ++i) {
9840 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9841 return_val_if_nok (error, NULL);
9842 mono_array_setref (result, i, attr);
9848 * mono_custom_attrs_from_index:
9850 * Returns: NULL if no attributes are found or if a loading error occurs.
9853 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9856 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9857 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9861 * mono_custom_attrs_from_index_checked:
9863 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9866 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9868 guint32 mtoken, i, len;
9869 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9871 MonoCustomAttrInfo *ainfo;
9872 GList *tmp, *list = NULL;
9874 MonoCustomAttrEntry* attr;
9876 mono_error_init (error);
9878 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9880 i = mono_metadata_custom_attrs_from_index (image, idx);
9884 while (i < ca->rows) {
9885 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9887 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9890 len = g_list_length (list);
9893 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9894 ainfo->num_attrs = len;
9895 ainfo->image = image;
9896 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9897 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9898 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9899 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9900 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9901 mtoken |= MONO_TOKEN_METHOD_DEF;
9903 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9904 mtoken |= MONO_TOKEN_MEMBER_REF;
9907 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9910 attr = &ainfo->attrs [i - 1];
9911 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9913 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9919 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9920 /*FIXME raising an exception here doesn't make any sense*/
9921 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9926 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9927 attr->data_size = mono_metadata_decode_value (data, &data);
9928 attr->data = (guchar*)data;
9936 mono_custom_attrs_from_method (MonoMethod *method)
9939 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9940 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9945 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9949 mono_error_init (error);
9952 * An instantiated method has the same cattrs as the generic method definition.
9954 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9955 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9957 if (method->is_inflated)
9958 method = ((MonoMethodInflated *) method)->declaring;
9960 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9961 return lookup_custom_attr (method->klass->image, method);
9964 /* Synthetic methods */
9967 idx = mono_method_get_index (method);
9968 idx <<= MONO_CUSTOM_ATTR_BITS;
9969 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9970 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9974 mono_custom_attrs_from_class (MonoClass *klass)
9977 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9978 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9983 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9987 mono_error_init (error);
9989 if (klass->generic_class)
9990 klass = klass->generic_class->container_class;
9992 if (image_is_dynamic (klass->image))
9993 return lookup_custom_attr (klass->image, klass);
9995 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9996 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9997 idx <<= MONO_CUSTOM_ATTR_BITS;
9998 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10000 idx = mono_metadata_token_index (klass->type_token);
10001 idx <<= MONO_CUSTOM_ATTR_BITS;
10002 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10004 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10007 MonoCustomAttrInfo*
10008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10011 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10012 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10016 MonoCustomAttrInfo*
10017 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10021 mono_error_init (error);
10023 if (image_is_dynamic (assembly->image))
10024 return lookup_custom_attr (assembly->image, assembly);
10025 idx = 1; /* there is only one assembly */
10026 idx <<= MONO_CUSTOM_ATTR_BITS;
10027 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10028 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10031 static MonoCustomAttrInfo*
10032 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10036 if (image_is_dynamic (image))
10037 return lookup_custom_attr (image, image);
10038 idx = 1; /* there is only one module */
10039 idx <<= MONO_CUSTOM_ATTR_BITS;
10040 idx |= MONO_CUSTOM_ATTR_MODULE;
10041 return mono_custom_attrs_from_index_checked (image, idx, error);
10044 MonoCustomAttrInfo*
10045 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10048 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10049 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10053 MonoCustomAttrInfo*
10054 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10058 if (image_is_dynamic (klass->image)) {
10059 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10060 return lookup_custom_attr (klass->image, property);
10062 idx = find_property_index (klass, property);
10063 idx <<= MONO_CUSTOM_ATTR_BITS;
10064 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10065 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10068 MonoCustomAttrInfo*
10069 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10072 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10073 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10077 MonoCustomAttrInfo*
10078 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10082 if (image_is_dynamic (klass->image)) {
10083 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10084 return lookup_custom_attr (klass->image, event);
10086 idx = find_event_index (klass, event);
10087 idx <<= MONO_CUSTOM_ATTR_BITS;
10088 idx |= MONO_CUSTOM_ATTR_EVENT;
10089 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10092 MonoCustomAttrInfo*
10093 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10096 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10097 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10101 MonoCustomAttrInfo*
10102 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10105 mono_error_init (error);
10107 if (image_is_dynamic (klass->image)) {
10108 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10109 return lookup_custom_attr (klass->image, field);
10111 idx = find_field_index (klass, field);
10112 idx <<= MONO_CUSTOM_ATTR_BITS;
10113 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10114 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10118 * mono_custom_attrs_from_param:
10119 * @method: handle to the method that we want to retrieve custom parameter information from
10120 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10122 * The result must be released with mono_custom_attrs_free().
10124 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10130 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10131 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10136 * mono_custom_attrs_from_param_checked:
10137 * @method: handle to the method that we want to retrieve custom parameter information from
10138 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10139 * @error: set on error
10141 * The result must be released with mono_custom_attrs_free().
10143 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10145 MonoCustomAttrInfo*
10146 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10149 guint32 i, idx, method_index;
10150 guint32 param_list, param_last, param_pos, found;
10152 MonoReflectionMethodAux *aux;
10154 mono_error_init (error);
10157 * An instantiated method has the same cattrs as the generic method definition.
10159 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10160 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10162 if (method->is_inflated)
10163 method = ((MonoMethodInflated *) method)->declaring;
10165 if (image_is_dynamic (method->klass->image)) {
10166 MonoCustomAttrInfo *res, *ainfo;
10169 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10170 if (!aux || !aux->param_cattr)
10173 /* Need to copy since it will be freed later */
10174 ainfo = aux->param_cattr [param];
10177 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10178 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10179 memcpy (res, ainfo, size);
10183 image = method->klass->image;
10184 method_index = mono_method_get_index (method);
10187 ca = &image->tables [MONO_TABLE_METHOD];
10189 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10190 if (method_index == ca->rows) {
10191 ca = &image->tables [MONO_TABLE_PARAM];
10192 param_last = ca->rows + 1;
10194 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10195 ca = &image->tables [MONO_TABLE_PARAM];
10198 for (i = param_list; i < param_last; ++i) {
10199 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10200 if (param_pos == param) {
10208 idx <<= MONO_CUSTOM_ATTR_BITS;
10209 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10210 return mono_custom_attrs_from_index_checked (image, idx, error);
10214 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10218 for (i = 0; i < ainfo->num_attrs; ++i) {
10219 klass = ainfo->attrs [i].ctor->klass;
10220 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10227 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10230 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10231 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10236 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10242 mono_error_init (error);
10245 for (i = 0; i < ainfo->num_attrs; ++i) {
10246 klass = ainfo->attrs [i].ctor->klass;
10247 if (mono_class_has_parent (klass, attr_klass)) {
10252 if (attr_index == -1)
10255 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10256 if (!mono_error_ok (error))
10258 return mono_array_get (attrs, MonoObject*, attr_index);
10262 * mono_reflection_get_custom_attrs_info:
10263 * @obj: a reflection object handle
10265 * Return the custom attribute info for attributes defined for the
10266 * reflection handle @obj. The objects.
10268 * FIXME this function leaks like a sieve for SRE objects.
10270 MonoCustomAttrInfo*
10271 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10274 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10275 mono_error_assert_ok (&error);
10280 * mono_reflection_get_custom_attrs_info_checked:
10281 * @obj: a reflection object handle
10282 * @error: set on error
10284 * Return the custom attribute info for attributes defined for the
10285 * reflection handle @obj. The objects.
10287 * On failure returns NULL and sets @error.
10289 * FIXME this function leaks like a sieve for SRE objects.
10291 MonoCustomAttrInfo*
10292 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10295 MonoCustomAttrInfo *cinfo = NULL;
10297 mono_error_init (error);
10299 klass = obj->vtable->klass;
10300 if (klass == mono_defaults.monotype_class) {
10301 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10302 return_val_if_nok (error, NULL);
10303 klass = mono_class_from_mono_type (type);
10304 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10305 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10306 return_val_if_nok (error, NULL);
10307 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10308 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10309 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10310 return_val_if_nok (error, NULL);
10311 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10312 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10313 cinfo = mono_custom_attrs_from_module (module->image, error);
10314 return_val_if_nok (error, NULL);
10315 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10316 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10317 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10318 return_val_if_nok (error, NULL);
10319 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10320 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10321 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10322 return_val_if_nok (error, NULL);
10323 } else if (strcmp ("MonoField", klass->name) == 0) {
10324 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10325 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10326 return_val_if_nok (error, NULL);
10327 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10328 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10329 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10330 return_val_if_nok (error, NULL);
10331 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10332 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10333 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10334 return_val_if_nok (error, NULL);
10335 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10336 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10337 MonoClass *member_class = mono_object_class (param->MemberImpl);
10338 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10339 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10340 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10341 return_val_if_nok (error, NULL);
10342 } else if (is_sr_mono_property (member_class)) {
10343 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10344 MonoMethod *method;
10345 if (!(method = prop->property->get))
10346 method = prop->property->set;
10349 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10350 return_val_if_nok (error, NULL);
10352 #ifndef DISABLE_REFLECTION_EMIT
10353 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10354 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10355 return_val_if_nok (error, NULL);
10356 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10357 return_val_if_nok (error, NULL);
10358 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10359 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10360 MonoMethod *method = NULL;
10361 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10362 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10363 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10364 method = ((MonoReflectionMethod *)c->cb)->method;
10366 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));
10368 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10369 return_val_if_nok (error, NULL);
10373 char *type_name = mono_type_get_full_name (member_class);
10374 mono_error_set_not_supported (error,
10375 "Custom attributes on a ParamInfo with member %s are not supported",
10377 g_free (type_name);
10380 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10381 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10382 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10383 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10384 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10385 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10386 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10387 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10388 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10389 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10390 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10391 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10392 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10393 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10394 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10395 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10396 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10397 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10398 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10399 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10400 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10401 return_val_if_nok (error, NULL);
10402 } else { /* handle other types here... */
10403 g_error ("get custom attrs not yet supported for %s", klass->name);
10410 * mono_reflection_get_custom_attrs_by_type:
10411 * @obj: a reflection object handle
10413 * Return an array with all the custom attributes defined of the
10414 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10415 * of that type are returned. The objects are fully build. Return NULL if a loading error
10419 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10422 MonoCustomAttrInfo *cinfo;
10424 mono_error_init (error);
10426 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10427 return_val_if_nok (error, NULL);
10429 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10432 if (!cinfo->cached)
10433 mono_custom_attrs_free (cinfo);
10435 mono_loader_assert_no_error ();
10436 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10443 * mono_reflection_get_custom_attrs:
10444 * @obj: a reflection object handle
10446 * Return an array with all the custom attributes defined of the
10447 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10451 mono_reflection_get_custom_attrs (MonoObject *obj)
10455 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10459 * mono_reflection_get_custom_attrs_data:
10460 * @obj: a reflection obj handle
10462 * Returns an array of System.Reflection.CustomAttributeData,
10463 * which include information about attributes reflected on
10464 * types loaded using the Reflection Only methods
10467 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10471 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10472 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10477 * mono_reflection_get_custom_attrs_data_checked:
10478 * @obj: a reflection obj handle
10479 * @error: set on error
10481 * Returns an array of System.Reflection.CustomAttributeData,
10482 * which include information about attributes reflected on
10483 * types loaded using the Reflection Only methods
10486 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10489 MonoCustomAttrInfo *cinfo;
10491 mono_error_init (error);
10493 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10494 return_val_if_nok (error, NULL);
10496 result = mono_custom_attrs_data_construct (cinfo, error);
10497 return_val_if_nok (error, NULL);
10498 if (!cinfo->cached)
10499 mono_custom_attrs_free (cinfo);
10501 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10503 if (mono_loader_get_last_error ())
10504 mono_error_set_from_loader_error (error);
10509 static MonoReflectionType*
10510 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10512 static MonoMethod *method_get_underlying_system_type = NULL;
10513 MonoReflectionType *rt;
10514 MonoMethod *usertype_method;
10516 mono_error_init (error);
10518 if (!method_get_underlying_system_type)
10519 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10521 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10523 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10530 is_corlib_type (MonoClass *klass)
10532 return klass->image == mono_defaults.corlib;
10535 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10536 static MonoClass *cached_class; \
10537 if (cached_class) \
10538 return cached_class == _class; \
10539 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10540 cached_class = _class; \
10547 #ifndef DISABLE_REFLECTION_EMIT
10549 is_sre_array (MonoClass *klass)
10551 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10555 is_sre_byref (MonoClass *klass)
10557 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10561 is_sre_pointer (MonoClass *klass)
10563 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10567 is_sre_generic_instance (MonoClass *klass)
10569 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10573 is_sre_type_builder (MonoClass *klass)
10575 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10579 is_sre_method_builder (MonoClass *klass)
10581 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10585 is_sre_ctor_builder (MonoClass *klass)
10587 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10591 is_sre_field_builder (MonoClass *klass)
10593 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10597 is_sre_method_on_tb_inst (MonoClass *klass)
10599 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10603 is_sre_ctor_on_tb_inst (MonoClass *klass)
10605 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10609 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10612 mono_error_init (error);
10619 if (is_usertype (ref)) {
10620 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10621 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10627 klass = mono_object_class (ref);
10629 if (is_sre_array (klass)) {
10631 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10632 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10633 return_val_if_nok (error, NULL);
10635 if (sre_array->rank == 0) //single dimentional array
10636 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10638 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10639 sre_array->type.type = res;
10641 } else if (is_sre_byref (klass)) {
10643 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10644 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10645 return_val_if_nok (error, NULL);
10647 res = &mono_class_from_mono_type (base)->this_arg;
10648 sre_byref->type.type = res;
10650 } else if (is_sre_pointer (klass)) {
10652 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10653 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10654 return_val_if_nok (error, NULL);
10656 res = &mono_ptr_class_get (base)->byval_arg;
10657 sre_pointer->type.type = res;
10659 } else if (is_sre_generic_instance (klass)) {
10660 MonoType *res, **types;
10661 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10664 count = mono_array_length (gclass->type_arguments);
10665 types = g_new0 (MonoType*, count);
10666 for (i = 0; i < count; ++i) {
10667 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10668 types [i] = mono_reflection_type_get_handle (t, error);
10669 if (!types[i] || !is_ok (error)) {
10675 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10678 gclass->type.type = res;
10682 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10687 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10690 mono_reflection_type_get_handle (type, &error);
10691 mono_error_set_pending_exception (&error);
10695 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10697 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10700 mono_error_init (error);
10702 MonoType *res = mono_reflection_type_get_handle (type, error);
10704 if (!res && is_ok (error)) {
10705 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10707 return_val_if_nok (error, FALSE);
10709 klass = mono_class_from_mono_type (res);
10711 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10712 mono_domain_lock (domain);
10714 if (!image_is_dynamic (klass->image)) {
10715 mono_class_setup_supertypes (klass);
10717 if (!domain->type_hash)
10718 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10719 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10720 mono_g_hash_table_insert (domain->type_hash, res, type);
10722 mono_domain_unlock (domain);
10723 mono_loader_unlock ();
10729 mono_reflection_register_with_runtime (MonoReflectionType *type)
10732 (void) reflection_register_with_runtime (type, &error);
10733 mono_error_set_pending_exception (&error);
10737 * LOCKING: Assumes the loader lock is held.
10739 static MonoMethodSignature*
10740 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10741 MonoMethodSignature *sig;
10744 mono_error_init (error);
10746 count = parameters? mono_array_length (parameters): 0;
10748 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10749 sig->param_count = count;
10750 sig->sentinelpos = -1; /* FIXME */
10751 for (i = 0; i < count; ++i) {
10752 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10753 if (!is_ok (error)) {
10754 image_g_free (image, sig);
10762 * LOCKING: Assumes the loader lock is held.
10764 static MonoMethodSignature*
10765 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10766 MonoMethodSignature *sig;
10768 mono_error_init (error);
10770 sig = parameters_to_signature (image, ctor->parameters, error);
10771 return_val_if_nok (error, NULL);
10772 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10773 sig->ret = &mono_defaults.void_class->byval_arg;
10778 * LOCKING: Assumes the loader lock is held.
10780 static MonoMethodSignature*
10781 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10782 MonoMethodSignature *sig;
10784 mono_error_init (error);
10786 sig = parameters_to_signature (image, method->parameters, error);
10787 return_val_if_nok (error, NULL);
10788 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10789 if (method->rtype) {
10790 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10791 if (!is_ok (error)) {
10792 image_g_free (image, sig);
10796 sig->ret = &mono_defaults.void_class->byval_arg;
10798 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10802 static MonoMethodSignature*
10803 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10804 MonoMethodSignature *sig;
10806 mono_error_init (error);
10808 sig = parameters_to_signature (NULL, method->parameters, error);
10809 return_val_if_nok (error, NULL);
10810 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10811 if (method->rtype) {
10812 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10813 if (!is_ok (error)) {
10818 sig->ret = &mono_defaults.void_class->byval_arg;
10820 sig->generic_param_count = 0;
10825 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10827 mono_error_init (error);
10828 MonoClass *klass = mono_object_class (prop);
10829 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10830 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10831 *name = mono_string_to_utf8 (pb->name);
10832 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10834 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10835 *name = g_strdup (p->property->name);
10836 if (p->property->get)
10837 *type = mono_method_signature (p->property->get)->ret;
10839 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10844 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10846 mono_error_init (error);
10847 MonoClass *klass = mono_object_class (field);
10848 if (strcmp (klass->name, "FieldBuilder") == 0) {
10849 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10850 *name = mono_string_to_utf8 (fb->name);
10851 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10853 MonoReflectionField *f = (MonoReflectionField *)field;
10854 *name = g_strdup (mono_field_get_name (f->field));
10855 *type = f->field->type;
10859 #else /* DISABLE_REFLECTION_EMIT */
10862 mono_reflection_register_with_runtime (MonoReflectionType *type)
10864 /* This is empty */
10868 is_sre_type_builder (MonoClass *klass)
10874 is_sre_generic_instance (MonoClass *klass)
10880 init_type_builder_generics (MonoObject *type)
10884 #endif /* !DISABLE_REFLECTION_EMIT */
10888 is_sr_mono_field (MonoClass *klass)
10890 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10894 is_sr_mono_property (MonoClass *klass)
10896 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10900 is_sr_mono_method (MonoClass *klass)
10902 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10906 is_sr_mono_cmethod (MonoClass *klass)
10908 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10912 is_sr_mono_generic_method (MonoClass *klass)
10914 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10918 is_sr_mono_generic_cmethod (MonoClass *klass)
10920 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10924 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10926 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10930 is_usertype (MonoReflectionType *ref)
10932 MonoClass *klass = mono_object_class (ref);
10933 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10936 static MonoReflectionType*
10937 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10939 mono_error_init (error);
10940 if (!type || type->type)
10943 if (is_usertype (type)) {
10944 type = mono_reflection_type_get_underlying_system_type (type, error);
10945 return_val_if_nok (error, NULL);
10946 if (is_usertype (type)) {
10947 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10955 * encode_cattr_value:
10956 * Encode a value in a custom attribute stream of bytes.
10957 * The value to encode is either supplied as an object in argument val
10958 * (valuetypes are boxed), or as a pointer to the data in the
10960 * @type represents the type of the value
10961 * @buffer is the start of the buffer
10962 * @p the current position in the buffer
10963 * @buflen contains the size of the buffer and is used to return the new buffer size
10964 * if this needs to be realloced.
10965 * @retbuffer and @retp return the start and the position of the buffer
10966 * @error set on error.
10969 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10971 MonoTypeEnum simple_type;
10973 mono_error_init (error);
10974 if ((p-buffer) + 10 >= *buflen) {
10977 newbuf = (char *)g_realloc (buffer, *buflen);
10978 p = newbuf + (p-buffer);
10982 argval = ((char*)arg + sizeof (MonoObject));
10983 simple_type = type->type;
10985 switch (simple_type) {
10986 case MONO_TYPE_BOOLEAN:
10991 case MONO_TYPE_CHAR:
10994 swap_with_size (p, argval, 2, 1);
11000 swap_with_size (p, argval, 4, 1);
11004 swap_with_size (p, argval, 8, 1);
11009 swap_with_size (p, argval, 8, 1);
11012 case MONO_TYPE_VALUETYPE:
11013 if (type->data.klass->enumtype) {
11014 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11017 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11020 case MONO_TYPE_STRING: {
11027 str = mono_string_to_utf8 ((MonoString*)arg);
11028 slen = strlen (str);
11029 if ((p-buffer) + 10 + slen >= *buflen) {
11033 newbuf = (char *)g_realloc (buffer, *buflen);
11034 p = newbuf + (p-buffer);
11037 mono_metadata_encode_value (slen, p, &p);
11038 memcpy (p, str, slen);
11043 case MONO_TYPE_CLASS: {
11046 MonoType *arg_type;
11052 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11053 return_if_nok (error);
11055 str = type_get_qualified_name (arg_type, NULL);
11056 slen = strlen (str);
11057 if ((p-buffer) + 10 + slen >= *buflen) {
11061 newbuf = (char *)g_realloc (buffer, *buflen);
11062 p = newbuf + (p-buffer);
11065 mono_metadata_encode_value (slen, p, &p);
11066 memcpy (p, str, slen);
11071 case MONO_TYPE_SZARRAY: {
11073 MonoClass *eclass, *arg_eclass;
11076 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11079 len = mono_array_length ((MonoArray*)arg);
11081 *p++ = (len >> 8) & 0xff;
11082 *p++ = (len >> 16) & 0xff;
11083 *p++ = (len >> 24) & 0xff;
11085 *retbuffer = buffer;
11086 eclass = type->data.klass;
11087 arg_eclass = mono_object_class (arg)->element_class;
11090 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11091 eclass = mono_defaults.object_class;
11093 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11094 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11095 int elsize = mono_class_array_element_size (arg_eclass);
11096 for (i = 0; i < len; ++i) {
11097 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11098 return_if_nok (error);
11101 } else if (eclass->valuetype && arg_eclass->valuetype) {
11102 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11103 int elsize = mono_class_array_element_size (eclass);
11104 for (i = 0; i < len; ++i) {
11105 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11106 return_if_nok (error);
11110 for (i = 0; i < len; ++i) {
11111 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11112 return_if_nok (error);
11117 case MONO_TYPE_OBJECT: {
11123 * The parameter type is 'object' but the type of the actual
11124 * argument is not. So we have to add type information to the blob
11125 * too. This is completely undocumented in the spec.
11129 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11134 klass = mono_object_class (arg);
11136 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11140 return_if_nok (error);
11143 if (klass->enumtype) {
11145 } else if (klass == mono_defaults.string_class) {
11146 simple_type = MONO_TYPE_STRING;
11149 } else if (klass->rank == 1) {
11151 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11152 /* See Partition II, Appendix B3 */
11155 *p++ = klass->element_class->byval_arg.type;
11156 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11157 return_if_nok (error);
11159 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11160 *p++ = simple_type = klass->byval_arg.type;
11163 g_error ("unhandled type in custom attr");
11165 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11166 slen = strlen (str);
11167 if ((p-buffer) + 10 + slen >= *buflen) {
11171 newbuf = (char *)g_realloc (buffer, *buflen);
11172 p = newbuf + (p-buffer);
11175 mono_metadata_encode_value (slen, p, &p);
11176 memcpy (p, str, slen);
11179 simple_type = mono_class_enum_basetype (klass)->type;
11183 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11186 *retbuffer = buffer;
11190 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11192 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11193 char *str = type_get_qualified_name (type, NULL);
11194 int slen = strlen (str);
11198 * This seems to be optional...
11201 mono_metadata_encode_value (slen, p, &p);
11202 memcpy (p, str, slen);
11205 } else if (type->type == MONO_TYPE_OBJECT) {
11207 } else if (type->type == MONO_TYPE_CLASS) {
11208 /* it should be a type: encode_cattr_value () has the check */
11211 mono_metadata_encode_value (type->type, p, &p);
11212 if (type->type == MONO_TYPE_SZARRAY)
11213 /* See the examples in Partition VI, Annex B */
11214 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11220 #ifndef DISABLE_REFLECTION_EMIT
11222 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11226 mono_error_init (error);
11228 /* Preallocate a large enough buffer */
11229 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11230 char *str = type_get_qualified_name (type, NULL);
11231 len = strlen (str);
11233 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11234 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11235 len = strlen (str);
11240 len += strlen (name);
11242 if ((p-buffer) + 20 + len >= *buflen) {
11246 newbuf = (char *)g_realloc (buffer, *buflen);
11247 p = newbuf + (p-buffer);
11251 encode_field_or_prop_type (type, p, &p);
11253 len = strlen (name);
11254 mono_metadata_encode_value (len, p, &p);
11255 memcpy (p, name, len);
11257 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11258 return_if_nok (error);
11260 *retbuffer = buffer;
11264 * mono_reflection_get_custom_attrs_blob:
11265 * @ctor: custom attribute constructor
11266 * @ctorArgs: arguments o the constructor
11272 * Creates the blob of data that needs to be saved in the metadata and that represents
11273 * the custom attributed described by @ctor, @ctorArgs etc.
11274 * Returns: a Byte array representing the blob of data.
11277 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11280 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11281 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11286 * mono_reflection_get_custom_attrs_blob_checked:
11287 * @ctor: custom attribute constructor
11288 * @ctorArgs: arguments o the constructor
11293 * @error: set on error
11295 * Creates the blob of data that needs to be saved in the metadata and that represents
11296 * the custom attributed described by @ctor, @ctorArgs etc.
11297 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11300 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11302 MonoArray *result = NULL;
11303 MonoMethodSignature *sig;
11308 mono_error_init (error);
11310 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11311 /* sig is freed later so allocate it in the heap */
11312 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11313 if (!is_ok (error)) {
11318 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11321 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11323 p = buffer = (char *)g_malloc (buflen);
11324 /* write the prolog */
11327 for (i = 0; i < sig->param_count; ++i) {
11328 arg = mono_array_get (ctorArgs, MonoObject*, i);
11329 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11330 if (!is_ok (error)) goto leave;
11334 i += mono_array_length (properties);
11336 i += mono_array_length (fields);
11338 *p++ = (i >> 8) & 0xff;
11341 for (i = 0; i < mono_array_length (properties); ++i) {
11345 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11346 get_prop_name_and_type (prop, &pname, &ptype, error);
11347 if (!is_ok (error)) goto leave;
11348 *p++ = 0x54; /* PROPERTY signature */
11349 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11351 if (!is_ok (error)) goto leave;
11357 for (i = 0; i < mono_array_length (fields); ++i) {
11361 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11362 get_field_name_and_type (field, &fname, &ftype, error);
11363 if (!is_ok (error)) goto leave;
11364 *p++ = 0x53; /* FIELD signature */
11365 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11367 if (!is_ok (error)) goto leave;
11371 g_assert (p - buffer <= buflen);
11372 buflen = p - buffer;
11373 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11374 p = mono_array_addr (result, char, 0);
11375 memcpy (p, buffer, buflen);
11378 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11384 * reflection_setup_internal_class:
11385 * @tb: a TypeBuilder object
11386 * @error: set on error
11388 * Creates a MonoClass that represents the TypeBuilder.
11389 * This is a trick that lets us simplify a lot of reflection code
11390 * (and will allow us to support Build and Run assemblies easier).
11392 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11395 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11397 MonoClass *klass, *parent;
11399 mono_error_init (error);
11400 RESOLVE_TYPE (tb->parent, error);
11401 return_val_if_nok (error, FALSE);
11403 mono_loader_lock ();
11406 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11407 if (!is_ok (error)) {
11408 mono_loader_unlock ();
11411 /* check so we can compile corlib correctly */
11412 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11413 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11414 parent = parent_type->data.klass;
11416 parent = mono_class_from_mono_type (parent_type);
11422 /* the type has already being created: it means we just have to change the parent */
11423 if (tb->type.type) {
11424 klass = mono_class_from_mono_type (tb->type.type);
11425 klass->parent = NULL;
11426 /* fool mono_class_setup_parent */
11427 klass->supertypes = NULL;
11428 mono_class_setup_parent (klass, parent);
11429 mono_class_setup_mono_type (klass);
11430 mono_loader_unlock ();
11434 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11436 klass->image = &tb->module->dynamic_image->image;
11438 klass->inited = 1; /* we lie to the runtime */
11439 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11440 if (!is_ok (error))
11442 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11443 if (!is_ok (error))
11445 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11446 klass->flags = tb->attrs;
11448 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11450 klass->element_class = klass;
11452 if (mono_class_get_ref_info (klass) == NULL) {
11454 mono_class_set_ref_info (klass, tb);
11456 /* Put into cache so mono_class_get_checked () will find it.
11457 Skip nested types as those should not be available on the global scope. */
11458 if (!tb->nesting_type)
11459 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11462 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11463 by performing a mono_class_get which does the full resolution.
11465 Working around this semantics would require us to write a lot of code for no clear advantage.
11467 mono_image_append_class_to_reflection_info_set (klass);
11469 g_assert (mono_class_get_ref_info (klass) == tb);
11472 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11474 if (parent != NULL) {
11475 mono_class_setup_parent (klass, parent);
11476 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11477 const char *old_n = klass->name;
11478 /* trick to get relative numbering right when compiling corlib */
11479 klass->name = "BuildingObject";
11480 mono_class_setup_parent (klass, mono_defaults.object_class);
11481 klass->name = old_n;
11484 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11485 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11486 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11487 klass->instance_size = sizeof (MonoObject);
11488 klass->size_inited = 1;
11489 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11492 mono_class_setup_mono_type (klass);
11494 mono_class_setup_supertypes (klass);
11497 * FIXME: handle interfaces.
11500 tb->type.type = &klass->byval_arg;
11502 if (tb->nesting_type) {
11503 g_assert (tb->nesting_type->type);
11504 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11505 if (!is_ok (error)) goto failure;
11506 klass->nested_in = mono_class_from_mono_type (nesting_type);
11509 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11511 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11513 mono_loader_unlock ();
11517 mono_loader_unlock ();
11522 * mono_reflection_setup_internal_class:
11523 * @tb: a TypeBuilder object
11526 * Creates a MonoClass that represents the TypeBuilder.
11527 * This is a trick that lets us simplify a lot of reflection code
11528 * (and will allow us to support Build and Run assemblies easier).
11532 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11535 (void) reflection_setup_internal_class (tb, &error);
11536 mono_error_set_pending_exception (&error);
11540 * mono_reflection_setup_generic_class:
11541 * @tb: a TypeBuilder object
11543 * Setup the generic class before adding the first generic parameter.
11546 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11551 * mono_reflection_create_generic_class:
11552 * @tb: a TypeBuilder object
11554 * Creates the generic class after all generic parameters have been added.
11557 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11563 klass = mono_class_from_mono_type (tb->type.type);
11565 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11567 if (klass->generic_container || (count == 0))
11570 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11572 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11574 klass->generic_container->owner.klass = klass;
11575 klass->generic_container->type_argc = count;
11576 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11578 klass->is_generic = 1;
11580 for (i = 0; i < count; i++) {
11581 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11582 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11583 mono_error_raise_exception (&error); /* FIXME don't raise here */
11584 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11585 klass->generic_container->type_params [i] = *param;
11586 /*Make sure we are a diferent type instance */
11587 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11588 klass->generic_container->type_params [i].info.pklass = NULL;
11589 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11591 g_assert (klass->generic_container->type_params [i].param.owner);
11594 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11598 * reflection_create_internal_class:
11599 * @tb: a TypeBuilder object
11600 * @error: set on error
11602 * Actually create the MonoClass that is associated with the TypeBuilder.
11603 * On success returns TRUE, on failure returns FALSE and sets @error.
11607 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11612 mono_error_init (error);
11613 klass = mono_class_from_mono_type (tb->type.type);
11615 mono_loader_lock ();
11616 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11617 MonoReflectionFieldBuilder *fb;
11619 MonoType *enum_basetype;
11621 g_assert (tb->fields != NULL);
11622 g_assert (mono_array_length (tb->fields) >= 1);
11624 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11626 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11627 if (!is_ok (error)) {
11628 mono_loader_unlock ();
11631 if (!mono_type_is_valid_enum_basetype (field_type)) {
11632 mono_loader_unlock ();
11636 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11637 if (!is_ok (error)) {
11638 mono_loader_unlock ();
11641 klass->element_class = mono_class_from_mono_type (enum_basetype);
11642 if (!klass->element_class)
11643 klass->element_class = mono_class_from_mono_type (enum_basetype);
11646 * get the element_class from the current corlib.
11648 ec = default_class_from_mono_type (enum_basetype);
11649 klass->instance_size = ec->instance_size;
11650 klass->size_inited = 1;
11652 * this is almost safe to do with enums and it's needed to be able
11653 * to create objects of the enum type (for use in SetConstant).
11655 /* FIXME: Does this mean enums can't have method overrides ? */
11656 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11658 mono_loader_unlock ();
11663 * mono_reflection_create_internal_class:
11664 * @tb: a TypeBuilder object
11667 * Actually create the MonoClass that is associated with the TypeBuilder.
11670 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11673 (void) reflection_create_internal_class (tb, &error);
11674 mono_error_set_pending_exception (&error);
11677 static MonoMarshalSpec*
11678 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11679 MonoReflectionMarshal *minfo, MonoError *error)
11681 MonoMarshalSpec *res;
11683 mono_error_init (error);
11685 res = image_g_new0 (image, MonoMarshalSpec, 1);
11686 res->native = (MonoMarshalNative)minfo->type;
11688 switch (minfo->type) {
11689 case MONO_NATIVE_LPARRAY:
11690 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11691 if (minfo->has_size) {
11692 res->data.array_data.param_num = minfo->param_num;
11693 res->data.array_data.num_elem = minfo->count;
11694 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11697 res->data.array_data.param_num = -1;
11698 res->data.array_data.num_elem = -1;
11699 res->data.array_data.elem_mult = -1;
11703 case MONO_NATIVE_BYVALTSTR:
11704 case MONO_NATIVE_BYVALARRAY:
11705 res->data.array_data.num_elem = minfo->count;
11708 case MONO_NATIVE_CUSTOM:
11709 if (minfo->marshaltyperef) {
11710 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11711 if (!is_ok (error)) {
11712 image_g_free (image, res);
11715 res->data.custom_data.custom_name =
11716 type_get_fully_qualified_name (marshaltyperef);
11718 if (minfo->mcookie)
11719 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11728 #endif /* !DISABLE_REFLECTION_EMIT */
11730 MonoReflectionMarshalAsAttribute*
11731 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11732 MonoMarshalSpec *spec, MonoError *error)
11734 MonoReflectionType *rt;
11735 MonoReflectionMarshalAsAttribute *minfo;
11738 mono_error_init (error);
11740 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11743 minfo->utype = spec->native;
11745 switch (minfo->utype) {
11746 case MONO_NATIVE_LPARRAY:
11747 minfo->array_subtype = spec->data.array_data.elem_type;
11748 minfo->size_const = spec->data.array_data.num_elem;
11749 if (spec->data.array_data.param_num != -1)
11750 minfo->size_param_index = spec->data.array_data.param_num;
11753 case MONO_NATIVE_BYVALTSTR:
11754 case MONO_NATIVE_BYVALARRAY:
11755 minfo->size_const = spec->data.array_data.num_elem;
11758 case MONO_NATIVE_CUSTOM:
11759 if (spec->data.custom_data.custom_name) {
11760 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11761 return_val_if_nok (error, NULL);
11764 rt = mono_type_get_object_checked (domain, mtype, error);
11768 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11771 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11773 if (spec->data.custom_data.cookie)
11774 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11784 #ifndef DISABLE_REFLECTION_EMIT
11786 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11787 ReflectionMethodBuilder *rmb,
11788 MonoMethodSignature *sig)
11792 MonoMethodWrapper *wrapperm;
11793 MonoMarshalSpec **specs;
11794 MonoReflectionMethodAux *method_aux;
11799 mono_error_init (&error);
11801 * Methods created using a MethodBuilder should have their memory allocated
11802 * inside the image mempool, while dynamic methods should have their memory
11805 dynamic = rmb->refs != NULL;
11806 image = dynamic ? NULL : klass->image;
11809 g_assert (!klass->generic_class);
11811 mono_loader_lock ();
11813 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11814 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11815 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11817 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11819 wrapperm = (MonoMethodWrapper*)m;
11821 m->dynamic = dynamic;
11823 m->flags = rmb->attrs;
11824 m->iflags = rmb->iattrs;
11825 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11827 m->signature = sig;
11828 m->sre_method = TRUE;
11829 m->skip_visibility = rmb->skip_visibility;
11830 if (rmb->table_idx)
11831 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11833 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11834 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11835 m->string_ctor = 1;
11837 m->signature->pinvoke = 1;
11838 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11839 m->signature->pinvoke = 1;
11841 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11843 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11844 g_assert (mono_error_ok (&error));
11845 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11846 g_assert (mono_error_ok (&error));
11848 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11850 if (image_is_dynamic (klass->image))
11851 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11853 mono_loader_unlock ();
11856 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11857 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11858 MonoMethodHeader *header;
11860 gint32 max_stack, i;
11861 gint32 num_locals = 0;
11862 gint32 num_clauses = 0;
11866 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11867 code_size = rmb->ilgen->code_len;
11868 max_stack = rmb->ilgen->max_stack;
11869 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11870 if (rmb->ilgen->ex_handlers)
11871 num_clauses = method_count_clauses (rmb->ilgen);
11874 code = mono_array_addr (rmb->code, guint8, 0);
11875 code_size = mono_array_length (rmb->code);
11876 /* we probably need to run a verifier on the code... */
11886 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11887 header->code_size = code_size;
11888 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11889 memcpy ((char*)header->code, code, code_size);
11890 header->max_stack = max_stack;
11891 header->init_locals = rmb->init_locals;
11892 header->num_locals = num_locals;
11894 for (i = 0; i < num_locals; ++i) {
11895 MonoReflectionLocalBuilder *lb =
11896 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11898 header->locals [i] = image_g_new0 (image, MonoType, 1);
11899 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11900 mono_error_assert_ok (&error);
11901 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11904 header->num_clauses = num_clauses;
11906 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11907 rmb->ilgen, num_clauses, &error);
11908 mono_error_assert_ok (&error);
11911 wrapperm->header = header;
11914 if (rmb->generic_params) {
11915 int count = mono_array_length (rmb->generic_params);
11916 MonoGenericContainer *container = rmb->generic_container;
11918 g_assert (container);
11920 container->type_argc = count;
11921 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11922 container->owner.method = m;
11923 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11925 m->is_generic = TRUE;
11926 mono_method_set_generic_container (m, container);
11928 for (i = 0; i < count; i++) {
11929 MonoReflectionGenericParam *gp =
11930 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11931 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11932 mono_error_assert_ok (&error);
11933 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11934 container->type_params [i] = *param;
11938 * The method signature might have pointers to generic parameters that belong to other methods.
11939 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11940 * generic parameters.
11942 for (i = 0; i < m->signature->param_count; ++i) {
11943 MonoType *t = m->signature->params [i];
11944 if (t->type == MONO_TYPE_MVAR) {
11945 MonoGenericParam *gparam = t->data.generic_param;
11946 if (gparam->num < count) {
11947 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11948 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11954 if (klass->generic_container) {
11955 container->parent = klass->generic_container;
11956 container->context.class_inst = klass->generic_container->context.class_inst;
11958 container->context.method_inst = mono_get_shared_generic_inst (container);
11962 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11966 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11968 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11969 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11970 for (i = 0; i < rmb->nrefs; ++i)
11971 data [i + 1] = rmb->refs [i];
11976 /* Parameter info */
11979 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11980 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11981 for (i = 0; i <= m->signature->param_count; ++i) {
11982 MonoReflectionParamBuilder *pb;
11983 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11984 if ((i > 0) && (pb->attrs)) {
11985 /* Make a copy since it might point to a shared type structure */
11986 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11987 m->signature->params [i - 1]->attrs = pb->attrs;
11990 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11991 MonoDynamicImage *assembly;
11993 MonoTypeEnum def_type;
11997 if (!method_aux->param_defaults) {
11998 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11999 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12001 assembly = (MonoDynamicImage*)klass->image;
12002 idx = encode_constant (assembly, pb->def_value, &def_type);
12003 /* Copy the data from the blob since it might get realloc-ed */
12004 p = assembly->blob.data + idx;
12005 len = mono_metadata_decode_blob_size (p, &p2);
12007 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12008 method_aux->param_default_types [i] = def_type;
12009 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12013 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12014 g_assert (mono_error_ok (&error));
12017 if (!method_aux->param_cattr)
12018 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12019 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12025 /* Parameter marshalling */
12028 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12029 MonoReflectionParamBuilder *pb;
12030 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12031 if (pb->marshal_info) {
12033 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12034 specs [pb->position] =
12035 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12036 if (!is_ok (&error)) {
12037 mono_loader_unlock ();
12038 image_g_free (image, specs);
12039 mono_error_raise_exception (&error); /* FIXME don't raise here */
12044 if (specs != NULL) {
12046 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12047 method_aux->param_marshall = specs;
12050 if (image_is_dynamic (klass->image) && method_aux)
12051 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12053 mono_loader_unlock ();
12059 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12061 ReflectionMethodBuilder rmb;
12062 MonoMethodSignature *sig;
12064 mono_loader_lock ();
12065 g_assert (klass->image != NULL);
12066 sig = ctor_builder_to_signature (klass->image, mb, error);
12067 mono_loader_unlock ();
12068 return_val_if_nok (error, NULL);
12070 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12073 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12074 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12076 /* If we are in a generic class, we might be called multiple times from inflate_method */
12077 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12078 /* ilgen is no longer needed */
12082 return mb->mhandle;
12086 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12088 ReflectionMethodBuilder rmb;
12089 MonoMethodSignature *sig;
12091 mono_error_init (error);
12093 mono_loader_lock ();
12094 g_assert (klass->image != NULL);
12095 sig = method_builder_to_signature (klass->image, mb, error);
12096 mono_loader_unlock ();
12097 return_val_if_nok (error, NULL);
12099 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12102 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12103 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12105 /* If we are in a generic class, we might be called multiple times from inflate_method */
12106 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12107 /* ilgen is no longer needed */
12110 return mb->mhandle;
12113 static MonoClassField*
12114 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12116 MonoClassField *field;
12119 mono_error_init (error);
12121 field = g_new0 (MonoClassField, 1);
12123 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12124 mono_error_assert_ok (error);
12125 if (fb->attrs || fb->modreq || fb->modopt) {
12126 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12127 if (!is_ok (error)) {
12131 field->type = mono_metadata_type_dup (NULL, type);
12132 field->type->attrs = fb->attrs;
12134 g_assert (image_is_dynamic (klass->image));
12135 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12136 g_free (field->type);
12137 if (!is_ok (error)) {
12141 field->type = mono_metadata_type_dup (klass->image, custom);
12144 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12145 if (!is_ok (error)) {
12150 if (fb->offset != -1)
12151 field->offset = fb->offset;
12152 field->parent = klass;
12153 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12155 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12162 * mono_reflection_bind_generic_parameters:
12163 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12164 * @type_args: the number of type arguments to bind
12165 * @types: array of type arguments
12166 * @error: set on error
12168 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12169 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12172 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12175 MonoReflectionTypeBuilder *tb = NULL;
12176 gboolean is_dynamic = FALSE;
12177 MonoClass *geninst;
12179 mono_error_init (error);
12181 mono_loader_lock ();
12183 if (is_sre_type_builder (mono_object_class (type))) {
12184 tb = (MonoReflectionTypeBuilder *) type;
12187 } else if (is_sre_generic_instance (mono_object_class (type))) {
12188 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12189 MonoReflectionType *gtd = rgi->generic_type;
12191 if (is_sre_type_builder (mono_object_class (gtd))) {
12192 tb = (MonoReflectionTypeBuilder *)gtd;
12197 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12198 if (tb && tb->generic_container)
12199 mono_reflection_create_generic_class (tb);
12201 MonoType *t = mono_reflection_type_get_handle (type, error);
12202 if (!is_ok (error)) {
12203 mono_loader_unlock ();
12207 klass = mono_class_from_mono_type (t);
12208 if (!klass->generic_container) {
12209 mono_loader_unlock ();
12210 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12214 if (klass->wastypebuilder) {
12215 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12220 mono_loader_unlock ();
12222 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12224 return &geninst->byval_arg;
12228 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12230 MonoGenericClass *gclass;
12231 MonoGenericInst *inst;
12233 g_assert (klass->generic_container);
12235 inst = mono_metadata_get_generic_inst (type_argc, types);
12236 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12238 return mono_generic_class_get_class (gclass);
12241 MonoReflectionMethod*
12242 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12246 MonoMethod *method, *inflated;
12247 MonoMethodInflated *imethod;
12248 MonoGenericContext tmp_context;
12249 MonoGenericInst *ginst;
12250 MonoType **type_argv;
12253 /*FIXME but this no longer should happen*/
12254 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12255 #ifndef DISABLE_REFLECTION_EMIT
12256 MonoReflectionMethodBuilder *mb = NULL;
12260 mb = (MonoReflectionMethodBuilder *) rmethod;
12261 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12262 mono_error_raise_exception (&error); /* FIXME don't raise here */
12263 klass = mono_class_from_mono_type (tb);
12265 method = methodbuilder_to_mono_method (klass, mb, &error);
12267 mono_error_raise_exception (&error); /* FIXME don't raise here */
12269 g_assert_not_reached ();
12273 method = rmethod->method;
12276 klass = method->klass;
12278 if (method->is_inflated)
12279 method = ((MonoMethodInflated *) method)->declaring;
12281 count = mono_method_signature (method)->generic_param_count;
12282 if (count != mono_array_length (types))
12285 type_argv = g_new0 (MonoType *, count);
12286 for (i = 0; i < count; i++) {
12287 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12288 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12289 if (!is_ok (&error)) {
12290 g_free (type_argv);
12291 mono_error_raise_exception (&error); /* FIXME don't raise here */
12294 ginst = mono_metadata_get_generic_inst (count, type_argv);
12295 g_free (type_argv);
12297 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12298 tmp_context.method_inst = ginst;
12300 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12301 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12302 imethod = (MonoMethodInflated *) inflated;
12304 /*FIXME but I think this is no longer necessary*/
12305 if (image_is_dynamic (method->klass->image)) {
12306 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12308 * This table maps metadata structures representing inflated methods/fields
12309 * to the reflection objects representing their generic definitions.
12311 mono_image_lock ((MonoImage*)image);
12312 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12313 mono_image_unlock ((MonoImage*)image);
12316 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12317 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12319 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12320 mono_error_raise_exception (&error); /* FIXME don't raise here */
12324 #ifndef DISABLE_REFLECTION_EMIT
12326 static MonoMethod *
12327 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12329 MonoMethodInflated *imethod;
12330 MonoGenericContext *context;
12334 * With generic code sharing the klass might not be inflated.
12335 * This can happen because classes inflated with their own
12336 * type arguments are "normalized" to the uninflated class.
12338 if (!klass->generic_class)
12341 context = mono_class_get_context (klass);
12343 if (klass->method.count && klass->methods) {
12344 /* Find the already created inflated method */
12345 for (i = 0; i < klass->method.count; ++i) {
12346 g_assert (klass->methods [i]->is_inflated);
12347 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12350 g_assert (i < klass->method.count);
12351 imethod = (MonoMethodInflated*)klass->methods [i];
12354 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12355 mono_error_assert_ok (&error);
12358 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12359 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12361 mono_image_lock ((MonoImage*)image);
12362 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12363 mono_image_unlock ((MonoImage*)image);
12365 return (MonoMethod *) imethod;
12368 static MonoMethod *
12369 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12371 MonoMethod *method;
12374 mono_error_init (error);
12376 MonoClass *type_class = mono_object_class (type);
12378 if (is_sre_generic_instance (type_class)) {
12379 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12380 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12381 return_val_if_nok (error, NULL);
12382 gklass = mono_class_from_mono_type (generic_type);
12383 } else if (is_sre_type_builder (type_class)) {
12384 MonoType *t = mono_reflection_type_get_handle (type, error);
12385 return_val_if_nok (error, NULL);
12386 gklass = mono_class_from_mono_type (t);
12387 } else if (type->type) {
12388 gklass = mono_class_from_mono_type (type->type);
12389 gklass = mono_class_get_generic_type_definition (gklass);
12391 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12394 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12395 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12396 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12398 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12402 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12403 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12406 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12407 method = ((MonoReflectionMethod *) obj)->method;
12409 method = NULL; /* prevent compiler warning */
12410 g_error ("can't handle type %s", obj->vtable->klass->name);
12413 MonoType *t = mono_reflection_type_get_handle (type, error);
12414 return_val_if_nok (error, NULL);
12415 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12418 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12420 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12422 MonoGenericClass *gclass;
12423 MonoDynamicGenericClass *dgclass;
12424 MonoClass *klass, *gklass;
12428 mono_error_init (error);
12430 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12431 return_val_if_nok (error, FALSE);
12432 klass = mono_class_from_mono_type (gtype);
12433 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12434 gclass = gtype->data.generic_class;
12436 if (!gclass->is_dynamic)
12439 dgclass = (MonoDynamicGenericClass *) gclass;
12441 if (dgclass->initialized)
12444 gklass = gclass->container_class;
12445 mono_class_init (gklass);
12447 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12449 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12450 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12451 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12453 for (i = 0; i < dgclass->count_fields; i++) {
12454 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12455 MonoClassField *field, *inflated_field = NULL;
12457 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12458 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12459 return_val_if_nok (error, FALSE);
12460 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12461 field = ((MonoReflectionField *) obj)->field;
12463 field = NULL; /* prevent compiler warning */
12464 g_assert_not_reached ();
12467 dgclass->fields [i] = *field;
12468 dgclass->fields [i].parent = klass;
12469 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12470 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12471 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12472 dgclass->field_generic_types [i] = field->type;
12473 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12474 dgclass->field_objects [i] = obj;
12476 if (inflated_field) {
12477 g_free (inflated_field);
12479 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12483 dgclass->initialized = TRUE;
12488 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12491 (void) reflection_generic_class_initialize (type, fields, &error);
12492 mono_error_set_pending_exception (&error);
12496 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12498 MonoDynamicGenericClass *dgclass;
12501 g_assert (gclass->is_dynamic);
12503 dgclass = (MonoDynamicGenericClass *)gclass;
12505 for (i = 0; i < dgclass->count_fields; ++i) {
12506 MonoClassField *field = dgclass->fields + i;
12507 mono_metadata_free_type (field->type);
12508 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12513 * fix_partial_generic_class:
12514 * @klass: a generic instantiation MonoClass
12515 * @error: set on error
12517 * Assumes that the generic container of @klass has its vtable
12518 * initialized, and updates the parent class, insterfaces, methods and
12519 * fields of @klass by inflating the types using the generic context.
12521 * On success returns TRUE, on failure returns FALSE and sets @error.
12525 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12527 MonoClass *gklass = klass->generic_class->container_class;
12528 MonoDynamicGenericClass *dgclass;
12531 mono_error_init (error);
12533 if (klass->wastypebuilder)
12536 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12537 if (klass->parent != gklass->parent) {
12538 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12539 if (mono_error_ok (error)) {
12540 MonoClass *parent = mono_class_from_mono_type (parent_type);
12541 mono_metadata_free_type (parent_type);
12542 if (parent != klass->parent) {
12543 /*fool mono_class_setup_parent*/
12544 klass->supertypes = NULL;
12545 mono_class_setup_parent (klass, parent);
12548 if (gklass->wastypebuilder)
12549 klass->wastypebuilder = TRUE;
12554 if (!dgclass->initialized)
12557 if (klass->method.count != gklass->method.count) {
12558 klass->method.count = gklass->method.count;
12559 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12561 for (i = 0; i < klass->method.count; i++) {
12562 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12563 gklass->methods [i], klass, mono_class_get_context (klass), error);
12564 mono_error_assert_ok (error);
12568 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12569 klass->interface_count = gklass->interface_count;
12570 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12571 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12573 for (i = 0; i < gklass->interface_count; ++i) {
12574 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12575 return_val_if_nok (error, FALSE);
12577 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12578 mono_metadata_free_type (iface_type);
12580 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12583 klass->interfaces_inited = 1;
12586 if (klass->field.count != gklass->field.count) {
12587 klass->field.count = gklass->field.count;
12588 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12590 for (i = 0; i < klass->field.count; i++) {
12591 klass->fields [i] = gklass->fields [i];
12592 klass->fields [i].parent = klass;
12593 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12594 return_val_if_nok (error, FALSE);
12598 /*We can only finish with this klass once it's parent has as well*/
12599 if (gklass->wastypebuilder)
12600 klass->wastypebuilder = TRUE;
12605 * ensure_generic_class_runtime_vtable:
12606 * @klass a generic class
12607 * @error set on error
12609 * Ensures that the generic container of @klass has a vtable and
12610 * returns TRUE on success. On error returns FALSE and sets @error.
12613 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12615 MonoClass *gklass = klass->generic_class->container_class;
12617 mono_error_init (error);
12619 if (!ensure_runtime_vtable (gklass, error))
12622 return fix_partial_generic_class (klass, error);
12626 * ensure_runtime_vtable:
12628 * @error set on error
12630 * Ensures that @klass has a vtable and returns TRUE on success. On
12631 * error returns FALSE and sets @error.
12634 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12636 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12639 mono_error_init (error);
12641 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12644 if (!ensure_runtime_vtable (klass->parent, error))
12648 num = tb->ctors? mono_array_length (tb->ctors): 0;
12649 num += tb->num_methods;
12650 klass->method.count = num;
12651 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12652 num = tb->ctors? mono_array_length (tb->ctors): 0;
12653 for (i = 0; i < num; ++i) {
12654 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12657 klass->methods [i] = ctor;
12659 num = tb->num_methods;
12661 for (i = 0; i < num; ++i) {
12662 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12665 klass->methods [j++] = meth;
12668 if (tb->interfaces) {
12669 klass->interface_count = mono_array_length (tb->interfaces);
12670 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12671 for (i = 0; i < klass->interface_count; ++i) {
12672 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12673 return_val_if_nok (error, FALSE);
12674 klass->interfaces [i] = mono_class_from_mono_type (iface);
12675 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12678 klass->interfaces_inited = 1;
12680 } else if (klass->generic_class){
12681 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12682 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12687 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12689 for (i = 0; i < klass->method.count; ++i) {
12690 MonoMethod *im = klass->methods [i];
12691 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12692 im->slot = slot_num++;
12695 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12696 mono_class_setup_interface_offsets (klass);
12697 mono_class_setup_interface_id (klass);
12701 * The generic vtable is needed even if image->run is not set since some
12702 * runtime code like ves_icall_Type_GetMethodsByName depends on
12703 * method->slot being defined.
12707 * tb->methods could not be freed since it is used for determining
12708 * overrides during dynamic vtable construction.
12715 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12717 mono_error_init (error);
12718 MonoClass *klass = mono_object_class (method);
12719 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12720 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12721 return sr_method->method;
12723 if (is_sre_method_builder (klass)) {
12724 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12725 return mb->mhandle;
12727 if (is_sre_method_on_tb_inst (klass)) {
12728 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12729 MonoMethod *result;
12730 /*FIXME move this to a proper method and unify with resolve_object*/
12731 if (m->method_args) {
12732 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12734 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12735 return_val_if_nok (error, NULL);
12736 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12737 MonoMethod *mono_method;
12739 if (is_sre_method_builder (mono_object_class (m->mb)))
12740 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12741 else if (is_sr_mono_method (mono_object_class (m->mb)))
12742 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12744 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)));
12746 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12751 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12756 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12758 MonoReflectionTypeBuilder *tb;
12760 MonoReflectionMethod *m;
12762 mono_error_init (error);
12764 *num_overrides = 0;
12766 g_assert (image_is_dynamic (klass->image));
12768 if (!mono_class_get_ref_info (klass))
12771 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12773 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12777 for (i = 0; i < tb->num_methods; ++i) {
12778 MonoReflectionMethodBuilder *mb =
12779 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12780 if (mb->override_methods)
12781 onum += mono_array_length (mb->override_methods);
12786 *overrides = g_new0 (MonoMethod*, onum * 2);
12789 for (i = 0; i < tb->num_methods; ++i) {
12790 MonoReflectionMethodBuilder *mb =
12791 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12792 if (mb->override_methods) {
12793 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12794 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12796 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12797 return_if_nok (error);
12798 (*overrides) [onum * 2 + 1] = mb->mhandle;
12800 g_assert (mb->mhandle);
12808 *num_overrides = onum;
12812 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12814 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12815 MonoReflectionFieldBuilder *fb;
12816 MonoClassField *field;
12817 MonoImage *image = klass->image;
12818 const char *p, *p2;
12820 guint32 len, idx, real_size = 0;
12822 klass->field.count = tb->num_fields;
12823 klass->field.first = 0;
12825 mono_error_init (error);
12827 if (tb->class_size) {
12828 if ((tb->packing_size & 0xffffff00) != 0) {
12829 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12830 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12833 klass->packing_size = tb->packing_size;
12834 real_size = klass->instance_size + tb->class_size;
12837 if (!klass->field.count) {
12838 klass->instance_size = MAX (klass->instance_size, real_size);
12842 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12843 mono_class_alloc_ext (klass);
12844 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12846 This is, guess what, a hack.
12847 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12848 On the static path no field class is resolved, only types are built. This is the right thing to do
12850 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12852 klass->size_inited = 1;
12854 for (i = 0; i < klass->field.count; ++i) {
12855 MonoArray *rva_data;
12856 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12857 field = &klass->fields [i];
12858 field->name = mono_string_to_utf8_image (image, fb->name, error);
12859 if (!mono_error_ok (error))
12862 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12863 return_if_nok (error);
12864 field->type = mono_metadata_type_dup (klass->image, type);
12865 field->type->attrs = fb->attrs;
12867 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12868 return_if_nok (error);
12871 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12872 char *base = mono_array_addr (rva_data, char, 0);
12873 size_t size = mono_array_length (rva_data);
12874 char *data = (char *)mono_image_alloc (klass->image, size);
12875 memcpy (data, base, size);
12876 klass->ext->field_def_values [i].data = data;
12878 if (fb->offset != -1)
12879 field->offset = fb->offset;
12880 field->parent = klass;
12881 fb->handle = field;
12882 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12884 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12885 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12887 if (fb->def_value) {
12888 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12889 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12890 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12891 /* Copy the data from the blob since it might get realloc-ed */
12892 p = assembly->blob.data + idx;
12893 len = mono_metadata_decode_blob_size (p, &p2);
12895 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12896 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12900 klass->instance_size = MAX (klass->instance_size, real_size);
12901 mono_class_layout_fields (klass, klass->instance_size);
12905 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12907 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12908 MonoReflectionPropertyBuilder *pb;
12909 MonoImage *image = klass->image;
12910 MonoProperty *properties;
12913 mono_error_init (error);
12916 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12918 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12919 klass->ext->property.first = 0;
12921 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12922 klass->ext->properties = properties;
12923 for (i = 0; i < klass->ext->property.count; ++i) {
12924 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12925 properties [i].parent = klass;
12926 properties [i].attrs = pb->attrs;
12927 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12928 if (!mono_error_ok (error))
12930 if (pb->get_method)
12931 properties [i].get = pb->get_method->mhandle;
12932 if (pb->set_method)
12933 properties [i].set = pb->set_method->mhandle;
12935 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12936 if (pb->def_value) {
12938 const char *p, *p2;
12939 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12940 if (!klass->ext->prop_def_values)
12941 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12942 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12943 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12944 /* Copy the data from the blob since it might get realloc-ed */
12945 p = assembly->blob.data + idx;
12946 len = mono_metadata_decode_blob_size (p, &p2);
12948 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12949 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12954 static MonoReflectionEvent *
12955 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12957 mono_error_init (error);
12959 MonoEvent *event = g_new0 (MonoEvent, 1);
12962 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12963 if (!is_ok (error)) {
12967 klass = mono_class_from_mono_type (type);
12969 event->parent = klass;
12970 event->attrs = eb->attrs;
12971 event->name = mono_string_to_utf8 (eb->name);
12972 if (eb->add_method)
12973 event->add = eb->add_method->mhandle;
12974 if (eb->remove_method)
12975 event->remove = eb->remove_method->mhandle;
12976 if (eb->raise_method)
12977 event->raise = eb->raise_method->mhandle;
12979 #ifndef MONO_SMALL_CONFIG
12980 if (eb->other_methods) {
12982 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12983 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12984 MonoReflectionMethodBuilder *mb =
12985 mono_array_get (eb->other_methods,
12986 MonoReflectionMethodBuilder*, j);
12987 event->other [j] = mb->mhandle;
12992 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12993 if (!is_ok (error)) {
12994 #ifndef MONO_SMALL_CONFIG
12995 g_free (event->other);
13003 MonoReflectionEvent *
13004 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13007 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13008 mono_error_set_pending_exception (&error);
13013 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13015 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13016 MonoReflectionEventBuilder *eb;
13017 MonoImage *image = klass->image;
13021 mono_error_init (error);
13024 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13026 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13027 klass->ext->event.first = 0;
13029 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13030 klass->ext->events = events;
13031 for (i = 0; i < klass->ext->event.count; ++i) {
13032 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13033 events [i].parent = klass;
13034 events [i].attrs = eb->attrs;
13035 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13036 if (!mono_error_ok (error))
13038 if (eb->add_method)
13039 events [i].add = eb->add_method->mhandle;
13040 if (eb->remove_method)
13041 events [i].remove = eb->remove_method->mhandle;
13042 if (eb->raise_method)
13043 events [i].raise = eb->raise_method->mhandle;
13045 #ifndef MONO_SMALL_CONFIG
13046 if (eb->other_methods) {
13048 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13049 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13050 MonoReflectionMethodBuilder *mb =
13051 mono_array_get (eb->other_methods,
13052 MonoReflectionMethodBuilder*, j);
13053 events [i].other [j] = mb->mhandle;
13057 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13061 struct remove_instantiations_user_data
13068 remove_instantiations_of_and_ensure_contents (gpointer key,
13070 gpointer user_data)
13072 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13073 MonoType *type = (MonoType*)key;
13074 MonoClass *klass = data->klass;
13075 gboolean already_failed = !is_ok (data->error);
13077 MonoError *error = already_failed ? &lerror : data->error;
13079 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13080 MonoClass *inst_klass = mono_class_from_mono_type (type);
13081 //Ensure it's safe to use it.
13082 if (!fix_partial_generic_class (inst_klass, error)) {
13083 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13084 // Marked the class with failure, but since some other instantiation already failed,
13085 // just report that one, and swallow the error from this one.
13086 if (already_failed)
13087 mono_error_cleanup (error);
13095 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13097 mono_error_init (error);
13103 for (i = 0; i < mono_array_length (arr); ++i) {
13104 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13105 if (!mono_error_ok (error))
13110 MonoReflectionType*
13111 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13115 MonoDomain* domain;
13116 MonoReflectionType* res;
13119 mono_error_init (&error);
13121 domain = mono_object_domain (tb);
13122 klass = mono_class_from_mono_type (tb->type.type);
13125 * Check for user defined Type subclasses.
13127 RESOLVE_TYPE (tb->parent, &error);
13128 if (!is_ok (&error))
13129 goto failure_unlocked;
13130 check_array_for_usertypes (tb->interfaces, &error);
13131 if (!is_ok (&error))
13132 goto failure_unlocked;
13134 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13135 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13137 RESOLVE_TYPE (fb->type, &error);
13138 if (!is_ok (&error))
13139 goto failure_unlocked;
13140 check_array_for_usertypes (fb->modreq, &error);
13141 if (!is_ok (&error))
13142 goto failure_unlocked;
13143 check_array_for_usertypes (fb->modopt, &error);
13144 if (!is_ok (&error))
13145 goto failure_unlocked;
13146 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13147 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13148 if (!is_ok (&error))
13149 goto failure_unlocked;
13155 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13156 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13158 RESOLVE_TYPE (mb->rtype, &error);
13159 if (!is_ok (&error))
13160 goto failure_unlocked;
13161 check_array_for_usertypes (mb->return_modreq, &error);
13162 if (!is_ok (&error))
13163 goto failure_unlocked;
13164 check_array_for_usertypes (mb->return_modopt, &error);
13165 if (!is_ok (&error))
13166 goto failure_unlocked;
13167 check_array_for_usertypes (mb->parameters, &error);
13168 if (!is_ok (&error))
13169 goto failure_unlocked;
13170 if (mb->param_modreq)
13171 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13172 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13173 if (!is_ok (&error))
13174 goto failure_unlocked;
13176 if (mb->param_modopt)
13177 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13178 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13179 if (!is_ok (&error))
13180 goto failure_unlocked;
13186 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13187 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13189 check_array_for_usertypes (mb->parameters, &error);
13190 if (!is_ok (&error))
13191 goto failure_unlocked;
13192 if (mb->param_modreq)
13193 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13194 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13195 if (!is_ok (&error))
13196 goto failure_unlocked;
13198 if (mb->param_modopt)
13199 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13200 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13201 if (!is_ok (&error))
13202 goto failure_unlocked;
13208 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13211 * we need to lock the domain because the lock will be taken inside
13212 * So, we need to keep the locking order correct.
13214 mono_loader_lock ();
13215 mono_domain_lock (domain);
13216 if (klass->wastypebuilder) {
13217 mono_domain_unlock (domain);
13218 mono_loader_unlock ();
13220 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13221 mono_error_set_pending_exception (&error);
13226 * Fields to set in klass:
13227 * the various flags: delegate/unicode/contextbound etc.
13229 klass->flags = tb->attrs;
13230 klass->has_cctor = 1;
13231 klass->has_finalize = 1;
13232 klass->has_finalize_inited = 1;
13234 mono_class_setup_parent (klass, klass->parent);
13235 /* fool mono_class_setup_supertypes */
13236 klass->supertypes = NULL;
13237 mono_class_setup_supertypes (klass);
13238 mono_class_setup_mono_type (klass);
13241 if (!((MonoDynamicImage*)klass->image)->run) {
13242 if (klass->generic_container) {
13243 /* FIXME: The code below can't handle generic classes */
13244 klass->wastypebuilder = TRUE;
13245 mono_loader_unlock ();
13246 mono_domain_unlock (domain);
13248 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13249 mono_error_set_pending_exception (&error);
13256 /* enums are done right away */
13257 if (!klass->enumtype)
13258 if (!ensure_runtime_vtable (klass, &error))
13261 if (tb->subtypes) {
13262 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13263 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13264 mono_class_alloc_ext (klass);
13265 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13266 if (!is_ok (&error)) goto failure;
13267 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13271 klass->nested_classes_inited = TRUE;
13273 /* fields and object layout */
13274 if (klass->parent) {
13275 if (!klass->parent->size_inited)
13276 mono_class_init (klass->parent);
13277 klass->instance_size = klass->parent->instance_size;
13278 klass->sizes.class_size = 0;
13279 klass->min_align = klass->parent->min_align;
13280 /* if the type has no fields we won't call the field_setup
13281 * routine which sets up klass->has_references.
13283 klass->has_references |= klass->parent->has_references;
13285 klass->instance_size = sizeof (MonoObject);
13286 klass->min_align = 1;
13289 /* FIXME: handle packing_size and instance_size */
13290 typebuilder_setup_fields (klass, &error);
13291 if (!mono_error_ok (&error))
13293 typebuilder_setup_properties (klass, &error);
13294 if (!mono_error_ok (&error))
13297 typebuilder_setup_events (klass, &error);
13298 if (!mono_error_ok (&error))
13301 klass->wastypebuilder = TRUE;
13304 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13305 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13306 * we want to return normal System.MonoType objects, so clear these out from the cache.
13308 * Together with this we must ensure the contents of all instances to match the created type.
13310 if (domain->type_hash && klass->generic_container) {
13311 struct remove_instantiations_user_data data;
13312 data.klass = klass;
13313 data.error = &error;
13314 mono_error_assert_ok (&error);
13315 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13316 if (!is_ok (&error))
13320 mono_domain_unlock (domain);
13321 mono_loader_unlock ();
13323 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13324 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13325 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13326 goto failure_unlocked;
13329 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13330 if (!is_ok (&error))
13331 goto failure_unlocked;
13333 g_assert (res != (MonoReflectionType*)tb);
13338 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13339 klass->wastypebuilder = TRUE;
13340 mono_domain_unlock (domain);
13341 mono_loader_unlock ();
13343 mono_error_set_pending_exception (&error);
13348 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13350 MonoGenericParamFull *param;
13354 mono_error_init (error);
13356 image = &gparam->tbuilder->module->dynamic_image->image;
13358 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13360 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13361 mono_error_assert_ok (error);
13362 param->param.num = gparam->index;
13364 if (gparam->mbuilder) {
13365 if (!gparam->mbuilder->generic_container) {
13366 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13367 return_val_if_nok (error, FALSE);
13369 MonoClass *klass = mono_class_from_mono_type (tb);
13370 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13371 gparam->mbuilder->generic_container->is_method = TRUE;
13373 * Cannot set owner.method, since the MonoMethod is not created yet.
13374 * Set the image field instead, so type_in_image () works.
13376 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13377 gparam->mbuilder->generic_container->owner.image = klass->image;
13379 param->param.owner = gparam->mbuilder->generic_container;
13380 } else if (gparam->tbuilder) {
13381 if (!gparam->tbuilder->generic_container) {
13382 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13383 return_val_if_nok (error, FALSE);
13384 MonoClass *klass = mono_class_from_mono_type (tb);
13385 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13386 gparam->tbuilder->generic_container->owner.klass = klass;
13388 param->param.owner = gparam->tbuilder->generic_container;
13391 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13393 gparam->type.type = &pklass->byval_arg;
13395 mono_class_set_ref_info (pklass, gparam);
13396 mono_image_append_class_to_reflection_info_set (pklass);
13402 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13405 (void) reflection_initialize_generic_parameter (gparam, &error);
13406 mono_error_set_pending_exception (&error);
13411 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13414 MonoReflectionModuleBuilder *module = sig->module;
13415 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13416 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13421 check_array_for_usertypes (sig->arguments, &error);
13422 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13424 sigbuffer_init (&buf, 32);
13426 sigbuffer_add_value (&buf, 0x07);
13427 sigbuffer_add_value (&buf, na);
13428 if (assembly != NULL){
13429 for (i = 0; i < na; ++i) {
13430 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13431 encode_reflection_type (assembly, type, &buf, &error);
13432 if (!is_ok (&error)) goto fail;
13436 buflen = buf.p - buf.buf;
13437 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13438 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13439 sigbuffer_free (&buf);
13442 sigbuffer_free (&buf);
13443 mono_error_raise_exception (&error); /* FIXME don't raise here */
13448 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13451 MonoDynamicImage *assembly = sig->module->dynamic_image;
13452 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13457 check_array_for_usertypes (sig->arguments, &error);
13458 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13460 sigbuffer_init (&buf, 32);
13462 sigbuffer_add_value (&buf, 0x06);
13463 for (i = 0; i < na; ++i) {
13464 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13465 encode_reflection_type (assembly, type, &buf, &error);
13466 if (!is_ok (&error))
13470 buflen = buf.p - buf.buf;
13471 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13472 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13473 sigbuffer_free (&buf);
13477 sigbuffer_free (&buf);
13478 mono_error_raise_exception (&error); /* FIXME don't raise here */
13483 MonoMethod *handle;
13484 MonoDomain *domain;
13485 } DynamicMethodReleaseData;
13488 * The runtime automatically clean up those after finalization.
13490 static MonoReferenceQueue *dynamic_method_queue;
13493 free_dynamic_method (void *dynamic_method)
13495 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13496 MonoDomain *domain = data->domain;
13497 MonoMethod *method = data->handle;
13500 mono_domain_lock (domain);
13501 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13502 g_hash_table_remove (domain->method_to_dyn_method, method);
13503 mono_domain_unlock (domain);
13504 g_assert (dis_link);
13505 mono_gchandle_free (dis_link);
13507 mono_runtime_free_method (domain, method);
13512 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13514 MonoReferenceQueue *queue;
13515 MonoMethod *handle;
13516 DynamicMethodReleaseData *release_data;
13517 ReflectionMethodBuilder rmb;
13518 MonoMethodSignature *sig;
13520 MonoDomain *domain;
13524 mono_error_init (error);
13526 if (mono_runtime_is_shutting_down ()) {
13527 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13531 if (!(queue = dynamic_method_queue)) {
13532 mono_loader_lock ();
13533 if (!(queue = dynamic_method_queue))
13534 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13535 mono_loader_unlock ();
13538 sig = dynamic_method_to_signature (mb, error);
13539 return_val_if_nok (error, FALSE);
13541 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13544 * Resolve references.
13547 * Every second entry in the refs array is reserved for storing handle_class,
13548 * which is needed by the ldtoken implementation in the JIT.
13550 rmb.nrefs = mb->nrefs;
13551 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13552 for (i = 0; i < mb->nrefs; i += 2) {
13553 MonoClass *handle_class;
13555 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13557 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13558 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13560 * The referenced DynamicMethod should already be created by the managed
13561 * code, except in the case of circular references. In that case, we store
13562 * method in the refs array, and fix it up later when the referenced
13563 * DynamicMethod is created.
13565 if (method->mhandle) {
13566 ref = method->mhandle;
13568 /* FIXME: GC object stored in unmanaged memory */
13571 /* FIXME: GC object stored in unmanaged memory */
13572 method->referenced_by = g_slist_append (method->referenced_by, mb);
13574 handle_class = mono_defaults.methodhandle_class;
13576 MonoException *ex = NULL;
13577 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13578 if (!is_ok (error)) {
13583 ex = mono_get_exception_type_load (NULL, NULL);
13584 else if (mono_security_core_clr_enabled ())
13585 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13589 mono_error_set_exception_instance (error, ex);
13594 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13595 rmb.refs [i + 1] = handle_class;
13599 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13600 if (!is_ok (error)) {
13604 klass = mono_class_from_mono_type (owner_type);
13606 klass = mono_defaults.object_class;
13609 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13610 release_data = g_new (DynamicMethodReleaseData, 1);
13611 release_data->handle = handle;
13612 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13613 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13614 g_free (release_data);
13616 /* Fix up refs entries pointing at us */
13617 for (l = mb->referenced_by; l; l = l->next) {
13618 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13619 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13622 g_assert (method->mhandle);
13624 data = (gpointer*)wrapper->method_data;
13625 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13626 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13627 data [i + 1] = mb->mhandle;
13630 g_slist_free (mb->referenced_by);
13634 /* ilgen is no longer needed */
13637 domain = mono_domain_get ();
13638 mono_domain_lock (domain);
13639 if (!domain->method_to_dyn_method)
13640 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13641 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13642 mono_domain_unlock (domain);
13648 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13651 (void) reflection_create_dynamic_method (mb, &error);
13652 mono_error_set_pending_exception (&error);
13655 #endif /* DISABLE_REFLECTION_EMIT */
13659 * mono_reflection_is_valid_dynamic_token:
13661 * Returns TRUE if token is valid.
13665 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13667 return lookup_dyn_token (image, token) != NULL;
13670 MonoMethodSignature *
13671 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13673 MonoMethodSignature *sig;
13674 g_assert (image_is_dynamic (image));
13676 mono_error_init (error);
13678 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13682 return mono_method_signature_checked (method, error);
13685 #ifndef DISABLE_REFLECTION_EMIT
13688 * mono_reflection_lookup_dynamic_token:
13690 * Finish the Builder object pointed to by TOKEN and return the corresponding
13691 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13692 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13695 * LOCKING: Take the loader lock
13698 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13701 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13705 obj = lookup_dyn_token (assembly, token);
13708 g_error ("Could not find required dynamic token 0x%08x", token);
13714 handle_class = &klass;
13715 gpointer result = resolve_object (image, obj, handle_class, context, &error);
13716 mono_error_raise_exception (&error); /* FIXME don't raise here */
13721 * ensure_complete_type:
13723 * Ensure that KLASS is completed if it is a dynamic type, or references
13727 ensure_complete_type (MonoClass *klass, MonoError *error)
13729 mono_error_init (error);
13731 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13732 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13734 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13735 return_if_nok (error);
13737 // Asserting here could break a lot of code
13738 //g_assert (klass->wastypebuilder);
13741 if (klass->generic_class) {
13742 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13745 for (i = 0; i < inst->type_argc; ++i) {
13746 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13747 return_if_nok (error);
13753 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13755 gpointer result = NULL;
13757 mono_error_init (error);
13759 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13760 result = mono_string_intern_checked ((MonoString*)obj, error);
13761 return_val_if_nok (error, NULL);
13762 *handle_class = mono_defaults.string_class;
13764 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13765 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13766 return_val_if_nok (error, NULL);
13767 MonoClass *mc = mono_class_from_mono_type (type);
13768 if (!mono_class_init (mc)) {
13769 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13774 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13775 return_val_if_nok (error, NULL);
13777 result = mono_class_from_mono_type (inflated);
13778 mono_metadata_free_type (inflated);
13780 result = mono_class_from_mono_type (type);
13782 *handle_class = mono_defaults.typehandle_class;
13784 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13785 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13786 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13787 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13788 result = ((MonoReflectionMethod*)obj)->method;
13790 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13791 mono_error_assert_ok (error);
13793 *handle_class = mono_defaults.methodhandle_class;
13795 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13796 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13797 result = mb->mhandle;
13799 /* Type is not yet created */
13800 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13802 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13803 return_val_if_nok (error, NULL);
13806 * Hopefully this has been filled in by calling CreateType() on the
13810 * TODO: This won't work if the application finishes another
13811 * TypeBuilder instance instead of this one.
13813 result = mb->mhandle;
13816 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13817 mono_error_assert_ok (error);
13819 *handle_class = mono_defaults.methodhandle_class;
13820 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13821 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13823 result = cb->mhandle;
13825 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13827 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13828 return_val_if_nok (error, NULL);
13829 result = cb->mhandle;
13832 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13833 mono_error_assert_ok (error);
13835 *handle_class = mono_defaults.methodhandle_class;
13836 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13837 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13839 ensure_complete_type (field->parent, error);
13840 return_val_if_nok (error, NULL);
13843 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13844 return_val_if_nok (error, NULL);
13846 MonoClass *klass = mono_class_from_mono_type (inflated);
13847 MonoClassField *inflated_field;
13848 gpointer iter = NULL;
13849 mono_metadata_free_type (inflated);
13850 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13851 if (!strcmp (field->name, inflated_field->name))
13854 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13855 result = inflated_field;
13859 *handle_class = mono_defaults.fieldhandle_class;
13861 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13862 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13863 result = fb->handle;
13866 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13868 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13869 return_val_if_nok (error, NULL);
13870 result = fb->handle;
13873 if (fb->handle && fb->handle->parent->generic_container) {
13874 MonoClass *klass = fb->handle->parent;
13875 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13876 return_val_if_nok (error, NULL);
13878 MonoClass *inflated = mono_class_from_mono_type (type);
13880 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13882 mono_metadata_free_type (type);
13884 *handle_class = mono_defaults.fieldhandle_class;
13885 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13886 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13887 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13888 return_val_if_nok (error, NULL);
13891 klass = type->data.klass;
13892 if (klass->wastypebuilder) {
13893 /* Already created */
13897 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13898 return_val_if_nok (error, NULL);
13899 result = type->data.klass;
13902 *handle_class = mono_defaults.typehandle_class;
13903 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13904 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13905 MonoMethodSignature *sig;
13908 if (helper->arguments)
13909 nargs = mono_array_length (helper->arguments);
13913 sig = mono_metadata_signature_alloc (image, nargs);
13914 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13915 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13917 if (helper->unmanaged_call_conv) { /* unmanaged */
13918 sig->call_convention = helper->unmanaged_call_conv - 1;
13919 sig->pinvoke = TRUE;
13920 } else if (helper->call_conv & 0x02) {
13921 sig->call_convention = MONO_CALL_VARARG;
13923 sig->call_convention = MONO_CALL_DEFAULT;
13926 sig->param_count = nargs;
13927 /* TODO: Copy type ? */
13928 sig->ret = helper->return_type->type;
13929 for (i = 0; i < nargs; ++i) {
13930 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13931 if (!is_ok (error)) {
13932 image_g_free (image, sig);
13938 *handle_class = NULL;
13939 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13940 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13941 /* Already created by the managed code */
13942 g_assert (method->mhandle);
13943 result = method->mhandle;
13944 *handle_class = mono_defaults.methodhandle_class;
13945 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13946 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13947 return_val_if_nok (error, NULL);
13948 type = mono_class_inflate_generic_type_checked (type, context, error);
13949 return_val_if_nok (error, NULL);
13951 result = mono_class_from_mono_type (type);
13952 *handle_class = mono_defaults.typehandle_class;
13954 mono_metadata_free_type (type);
13955 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13956 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13957 return_val_if_nok (error, NULL);
13958 type = mono_class_inflate_generic_type_checked (type, context, error);
13959 return_val_if_nok (error, NULL);
13961 result = mono_class_from_mono_type (type);
13962 *handle_class = mono_defaults.typehandle_class;
13964 mono_metadata_free_type (type);
13965 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13966 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13967 MonoClass *inflated;
13969 MonoClassField *field;
13971 if (is_sre_field_builder (mono_object_class (f->fb)))
13972 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13973 else if (is_sr_mono_field (mono_object_class (f->fb)))
13974 field = ((MonoReflectionField*)f->fb)->field;
13976 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)));
13978 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13979 return_val_if_nok (error, NULL);
13980 type = mono_class_inflate_generic_type_checked (finst, context, error);
13981 return_val_if_nok (error, NULL);
13983 inflated = mono_class_from_mono_type (type);
13985 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13986 ensure_complete_type (field->parent, error);
13987 if (!is_ok (error)) {
13988 mono_metadata_free_type (type);
13993 mono_metadata_free_type (type);
13994 *handle_class = mono_defaults.fieldhandle_class;
13995 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13996 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13997 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
13998 return_val_if_nok (error, NULL);
13999 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14000 return_val_if_nok (error, NULL);
14002 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14003 MonoMethod *method;
14005 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14006 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14007 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14008 method = ((MonoReflectionMethod *)c->cb)->method;
14010 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)));
14012 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14013 *handle_class = mono_defaults.methodhandle_class;
14014 mono_metadata_free_type (type);
14015 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14016 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14017 if (m->method_args) {
14018 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14019 return_val_if_nok (error, NULL);
14021 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14022 mono_error_assert_ok (error);
14025 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14026 return_val_if_nok (error, NULL);
14027 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14028 return_val_if_nok (error, NULL);
14030 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14031 MonoMethod *method;
14033 if (is_sre_method_builder (mono_object_class (m->mb)))
14034 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14035 else if (is_sr_mono_method (mono_object_class (m->mb)))
14036 method = ((MonoReflectionMethod *)m->mb)->method;
14038 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)));
14040 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14041 mono_metadata_free_type (type);
14043 *handle_class = mono_defaults.methodhandle_class;
14044 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14045 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14048 MonoMethod *method;
14052 mtype = mono_reflection_type_get_handle (m->parent, error);
14053 return_val_if_nok (error, NULL);
14054 klass = mono_class_from_mono_type (mtype);
14056 /* Find the method */
14058 name = mono_string_to_utf8 (m->name);
14060 while ((method = mono_class_get_methods (klass, &iter))) {
14061 if (!strcmp (method->name, name))
14068 // FIXME: Check parameters/return value etc. match
14071 *handle_class = mono_defaults.methodhandle_class;
14072 } else if (is_sre_array (mono_object_get_class(obj)) ||
14073 is_sre_byref (mono_object_get_class(obj)) ||
14074 is_sre_pointer (mono_object_get_class(obj))) {
14075 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14076 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14077 return_val_if_nok (error, NULL);
14080 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14081 return_val_if_nok (error, NULL);
14083 result = mono_class_from_mono_type (inflated);
14084 mono_metadata_free_type (inflated);
14086 result = mono_class_from_mono_type (type);
14088 *handle_class = mono_defaults.typehandle_class;
14090 g_print ("%s\n", obj->vtable->klass->name);
14091 g_assert_not_reached ();
14096 #else /* DISABLE_REFLECTION_EMIT */
14099 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14101 g_assert_not_reached ();
14106 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14108 g_assert_not_reached ();
14112 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14114 g_assert_not_reached ();
14118 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14120 g_assert_not_reached ();
14124 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14126 g_assert_not_reached ();
14130 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14132 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14136 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14138 g_assert_not_reached ();
14142 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14144 g_assert_not_reached ();
14147 MonoReflectionModule *
14148 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14150 g_assert_not_reached ();
14155 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14157 g_assert_not_reached ();
14162 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14164 g_assert_not_reached ();
14169 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14170 gboolean create_open_instance, gboolean register_token, MonoError *error)
14172 g_assert_not_reached ();
14177 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14182 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14184 g_assert_not_reached ();
14188 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14190 mono_error_init (error);
14192 *num_overrides = 0;
14195 MonoReflectionEvent *
14196 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14198 g_assert_not_reached ();
14202 MonoReflectionType*
14203 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14205 g_assert_not_reached ();
14210 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14212 g_assert_not_reached ();
14216 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14218 g_assert_not_reached ();
14223 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14225 g_assert_not_reached ();
14230 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14235 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14241 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14243 mono_error_init (error);
14250 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14252 g_assert_not_reached ();
14255 #endif /* DISABLE_REFLECTION_EMIT */
14257 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14258 const static guint32 declsec_flags_map[] = {
14259 0x00000000, /* empty */
14260 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14261 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14262 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14263 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14264 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14265 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14266 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14267 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14268 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14269 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14270 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14271 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14272 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14273 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14274 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14275 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14276 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14277 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14281 * Returns flags that includes all available security action associated to the handle.
14282 * @token: metadata token (either for a class or a method)
14283 * @image: image where resides the metadata.
14286 mono_declsec_get_flags (MonoImage *image, guint32 token)
14288 int index = mono_metadata_declsec_from_index (image, token);
14289 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14290 guint32 result = 0;
14294 /* HasSecurity can be present for other, not specially encoded, attributes,
14295 e.g. SuppressUnmanagedCodeSecurityAttribute */
14299 for (i = index; i < t->rows; i++) {
14300 guint32 cols [MONO_DECL_SECURITY_SIZE];
14302 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14303 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14306 action = cols [MONO_DECL_SECURITY_ACTION];
14307 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14308 result |= declsec_flags_map [action];
14310 g_assert_not_reached ();
14317 * Get the security actions (in the form of flags) associated with the specified method.
14319 * @method: The method for which we want the declarative security flags.
14320 * Return the declarative security flags for the method (only).
14322 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14323 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14326 mono_declsec_flags_from_method (MonoMethod *method)
14328 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14329 /* FIXME: No cache (for the moment) */
14330 guint32 idx = mono_method_get_index (method);
14331 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14332 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14333 return mono_declsec_get_flags (method->klass->image, idx);
14339 * Get the security actions (in the form of flags) associated with the specified class.
14341 * @klass: The class for which we want the declarative security flags.
14342 * Return the declarative security flags for the class.
14344 * Note: We cache the flags inside the MonoClass structure as this will get
14345 * called very often (at least for each method).
14348 mono_declsec_flags_from_class (MonoClass *klass)
14350 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14351 if (!klass->ext || !klass->ext->declsec_flags) {
14354 idx = mono_metadata_token_index (klass->type_token);
14355 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14356 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14357 mono_loader_lock ();
14358 mono_class_alloc_ext (klass);
14359 mono_loader_unlock ();
14360 /* we cache the flags on classes */
14361 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14363 return klass->ext->declsec_flags;
14369 * Get the security actions (in the form of flags) associated with the specified assembly.
14371 * @assembly: The assembly for which we want the declarative security flags.
14372 * Return the declarative security flags for the assembly.
14375 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14377 guint32 idx = 1; /* there is only one assembly */
14378 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14379 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14380 return mono_declsec_get_flags (assembly->image, idx);
14385 * Fill actions for the specific index (which may either be an encoded class token or
14386 * an encoded method token) from the metadata image.
14387 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14390 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14391 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14393 MonoBoolean result = FALSE;
14395 guint32 cols [MONO_DECL_SECURITY_SIZE];
14396 int index = mono_metadata_declsec_from_index (image, token);
14399 t = &image->tables [MONO_TABLE_DECLSECURITY];
14400 for (i = index; i < t->rows; i++) {
14401 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14403 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14406 /* if present only replace (class) permissions with method permissions */
14407 /* if empty accept either class or method permissions */
14408 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14409 if (!actions->demand.blob) {
14410 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14411 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14412 actions->demand.blob = (char*) (blob + 2);
14413 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14416 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14417 if (!actions->noncasdemand.blob) {
14418 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14419 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14420 actions->noncasdemand.blob = (char*) (blob + 2);
14421 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14424 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14425 if (!actions->demandchoice.blob) {
14426 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14427 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14428 actions->demandchoice.blob = (char*) (blob + 2);
14429 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14439 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14440 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14442 guint32 idx = mono_metadata_token_index (klass->type_token);
14443 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14444 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14445 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14449 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14450 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14452 guint32 idx = mono_method_get_index (method);
14453 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14454 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14455 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14459 * Collect all actions (that requires to generate code in mini) assigned for
14460 * the specified method.
14461 * Note: Don't use the content of actions if the function return FALSE.
14464 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14466 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14467 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14468 MonoBoolean result = FALSE;
14471 /* quick exit if no declarative security is present in the metadata */
14472 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14475 /* we want the original as the wrapper is "free" of the security informations */
14476 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14477 method = mono_marshal_method_from_wrapper (method);
14482 /* First we look for method-level attributes */
14483 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14484 mono_class_init (method->klass);
14485 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14487 result = mono_declsec_get_method_demands_params (method, demands,
14488 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14491 /* Here we use (or create) the class declarative cache to look for demands */
14492 flags = mono_declsec_flags_from_class (method->klass);
14493 if (flags & mask) {
14495 mono_class_init (method->klass);
14496 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14498 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14499 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14502 /* The boolean return value is used as a shortcut in case nothing needs to
14503 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14509 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14511 * Note: Don't use the content of actions if the function return FALSE.
14514 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14516 MonoBoolean result = FALSE;
14519 /* quick exit if no declarative security is present in the metadata */
14520 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14523 /* we want the original as the wrapper is "free" of the security informations */
14524 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14525 method = mono_marshal_method_from_wrapper (method);
14530 /* results are independant - zeroize both */
14531 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14532 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14534 /* First we look for method-level attributes */
14535 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14536 mono_class_init (method->klass);
14538 result = mono_declsec_get_method_demands_params (method, cmethod,
14539 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14542 /* Here we use (or create) the class declarative cache to look for demands */
14543 flags = mono_declsec_flags_from_class (method->klass);
14544 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14545 mono_class_init (method->klass);
14547 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14548 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14555 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14557 * @klass The inherited class - this is the class that provides the security check (attributes)
14559 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14561 * Note: Don't use the content of actions if the function return FALSE.
14564 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14566 MonoBoolean result = FALSE;
14569 /* quick exit if no declarative security is present in the metadata */
14570 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14573 /* Here we use (or create) the class declarative cache to look for demands */
14574 flags = mono_declsec_flags_from_class (klass);
14575 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14576 mono_class_init (klass);
14577 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14579 result |= mono_declsec_get_class_demands_params (klass, demands,
14580 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14587 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14589 * Note: Don't use the content of actions if the function return FALSE.
14592 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14594 /* quick exit if no declarative security is present in the metadata */
14595 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14598 /* we want the original as the wrapper is "free" of the security informations */
14599 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14600 method = mono_marshal_method_from_wrapper (method);
14605 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14606 mono_class_init (method->klass);
14607 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14609 return mono_declsec_get_method_demands_params (method, demands,
14610 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14617 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14619 guint32 cols [MONO_DECL_SECURITY_SIZE];
14623 int index = mono_metadata_declsec_from_index (image, token);
14627 t = &image->tables [MONO_TABLE_DECLSECURITY];
14628 for (i = index; i < t->rows; i++) {
14629 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14631 /* shortcut - index are ordered */
14632 if (token != cols [MONO_DECL_SECURITY_PARENT])
14635 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14636 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14637 entry->blob = (char*) (metadata + 2);
14638 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14647 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14649 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14650 guint32 idx = mono_method_get_index (method);
14651 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14652 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14653 return get_declsec_action (method->klass->image, idx, action, entry);
14659 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14662 guint32 flags = mono_declsec_flags_from_class (klass);
14663 if (declsec_flags_map [action] & flags) {
14664 guint32 idx = mono_metadata_token_index (klass->type_token);
14665 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14666 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14667 return get_declsec_action (klass->image, idx, action, entry);
14673 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14675 guint32 idx = 1; /* there is only one assembly */
14676 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14677 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14679 return get_declsec_action (assembly->image, idx, action, entry);
14683 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14685 MonoObject *res, *exc;
14687 static MonoMethod *method = NULL;
14689 mono_error_init (error);
14691 if (method == NULL) {
14692 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14697 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14698 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14700 g_assert (mono_class_get_ref_info (klass));
14701 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14703 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14704 return_val_if_nok (error, FALSE);
14706 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14708 if (exc || !mono_error_ok (error)) {
14709 mono_error_cleanup (error);
14712 return *(MonoBoolean*)mono_object_unbox (res);
14716 * mono_reflection_type_get_type:
14717 * @reftype: the System.Type object
14719 * Returns the MonoType* associated with the C# System.Type object @reftype.
14722 mono_reflection_type_get_type (MonoReflectionType *reftype)
14724 g_assert (reftype);
14727 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14728 mono_error_assert_ok (&error);
14733 * mono_reflection_assembly_get_assembly:
14734 * @refassembly: the System.Reflection.Assembly object
14736 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14739 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14741 g_assert (refassembly);
14743 return refassembly->assembly;