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
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/mempool-internals.h>
41 #include <mono/metadata/security-core-clr.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-ptr-array.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/checked-build.h>
49 static gboolean is_usertype (MonoReflectionType *ref);
50 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA 0x00002000
65 MonoReflectionILGen *ilgen;
66 MonoReflectionType *rtype;
67 MonoArray *parameters;
68 MonoArray *generic_params;
69 MonoGenericContainer *generic_container;
75 guint32 *table_idx; /* note: it's a pointer */
79 MonoBoolean init_locals;
80 MonoBoolean skip_visibility;
81 MonoArray *return_modreq;
82 MonoArray *return_modopt;
83 MonoArray *param_modreq;
84 MonoArray *param_modopt;
85 MonoArray *permissions;
90 int charset, extra_flags, native_cc;
91 MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
96 MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
109 MONO_INTERFACEIMPL_SIZE,
110 MONO_MEMBERREF_SIZE, /* 0x0A */
112 MONO_CUSTOM_ATTR_SIZE,
113 MONO_FIELD_MARSHAL_SIZE,
114 MONO_DECL_SECURITY_SIZE,
115 MONO_CLASS_LAYOUT_SIZE,
116 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117 MONO_STAND_ALONE_SIGNATURE_SIZE,
121 MONO_PROPERTY_MAP_SIZE,
124 MONO_METHOD_SEMA_SIZE,
125 MONO_METHODIMPL_SIZE,
126 MONO_MODULEREF_SIZE, /* 0x1A */
132 MONO_ASSEMBLY_SIZE, /* 0x20 */
133 MONO_ASSEMBLY_PROCESSOR_SIZE,
134 MONO_ASSEMBLYOS_SIZE,
135 MONO_ASSEMBLYREF_SIZE,
136 MONO_ASSEMBLYREFPROC_SIZE,
137 MONO_ASSEMBLYREFOS_SIZE,
141 MONO_NESTED_CLASS_SIZE,
143 MONO_GENERICPARAM_SIZE, /* 0x2A */
144 MONO_METHODSPEC_SIZE,
145 MONO_GENPARCONSTRAINT_SIZE
149 #ifndef DISABLE_REFLECTION_EMIT
150 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
151 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
152 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
153 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
154 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
155 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
157 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
158 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
159 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
160 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
161 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
167 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
168 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
169 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
170 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
171 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
172 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
173 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
174 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
175 static gboolean is_sre_array (MonoClass *klass);
176 static gboolean is_sre_byref (MonoClass *klass);
177 static gboolean is_sre_pointer (MonoClass *klass);
178 static gboolean is_sre_type_builder (MonoClass *klass);
179 static gboolean is_sre_method_builder (MonoClass *klass);
180 static gboolean is_sre_ctor_builder (MonoClass *klass);
181 static gboolean is_sre_field_builder (MonoClass *klass);
182 static gboolean is_sr_mono_method (MonoClass *klass);
183 static gboolean is_sr_mono_cmethod (MonoClass *klass);
184 static gboolean is_sr_mono_generic_method (MonoClass *klass);
185 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
186 static gboolean is_sr_mono_field (MonoClass *klass);
187 static gboolean is_sr_mono_property (MonoClass *klass);
188 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
189 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
191 static gboolean type_is_reference (MonoType *type);
193 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
194 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
195 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
197 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
198 static void init_type_builder_generics (MonoObject *type, MonoError *error);
200 #define RESOLVE_TYPE(type, error) do { \
201 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
204 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205 __type = mono_reflection_type_resolve_user_types (__type, error); \
206 if (mono_error_ok (error)) \
207 mono_array_set (arr, MonoReflectionType*, index, __type); \
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
250 dynamic_images_lock (void)
252 mono_os_mutex_lock (&dynamic_images_mutex);
256 dynamic_images_unlock (void)
258 mono_os_mutex_unlock (&dynamic_images_mutex);
262 * mono_find_dynamic_image_owner:
264 * Find the dynamic image, if any, which a given pointer is located in the memory of.
267 mono_find_dynamic_image_owner (void *ptr)
269 MonoImage *owner = NULL;
272 dynamic_images_lock ();
276 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278 if (mono_mempool_contains_addr (image->mempool, ptr))
283 dynamic_images_unlock ();
289 mono_reflection_init (void)
291 mono_os_mutex_init (&dynamic_images_mutex);
295 dynamic_image_lock (MonoDynamicImage *image)
298 mono_image_lock ((MonoImage*)image);
303 dynamic_image_unlock (MonoDynamicImage *image)
305 mono_image_unlock ((MonoImage*)image);
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
311 MONO_REQ_GC_UNSAFE_MODE;
313 dynamic_image_lock (assembly);
314 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315 dynamic_image_unlock (assembly);
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
321 MONO_REQ_GC_UNSAFE_MODE;
325 dynamic_image_lock (assembly);
326 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327 dynamic_image_unlock (assembly);
333 sigbuffer_init (SigBuffer *buf, int size)
335 MONO_REQ_GC_NEUTRAL_MODE;
337 buf->buf = (char *)g_malloc (size);
339 buf->end = buf->buf + size;
343 sigbuffer_make_room (SigBuffer *buf, int size)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 if (buf->end - buf->p < size) {
348 int new_size = buf->end - buf->buf + size + 32;
349 char *p = (char *)g_realloc (buf->buf, new_size);
350 size = buf->p - buf->buf;
353 buf->end = buf->buf + new_size;
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
360 MONO_REQ_GC_NEUTRAL_MODE;
362 sigbuffer_make_room (buf, 6);
363 mono_metadata_encode_value (val, buf->p, &buf->p);
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
369 MONO_REQ_GC_NEUTRAL_MODE;
371 sigbuffer_make_room (buf, 1);
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
379 MONO_REQ_GC_NEUTRAL_MODE;
381 sigbuffer_make_room (buf, size);
382 memcpy (buf->p, p, size);
387 sigbuffer_free (SigBuffer *buf)
389 MONO_REQ_GC_NEUTRAL_MODE;
394 #ifndef DISABLE_REFLECTION_EMIT
398 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
402 image_g_malloc (MonoImage *image, guint size)
404 MONO_REQ_GC_NEUTRAL_MODE;
407 return mono_image_alloc (image, size);
409 return g_malloc (size);
411 #endif /* !DISABLE_REFLECTION_EMIT */
416 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
420 image_g_malloc0 (MonoImage *image, guint size)
422 MONO_REQ_GC_NEUTRAL_MODE;
425 return mono_image_alloc0 (image, size);
427 return g_malloc0 (size);
432 * @image: a MonoImage
435 * If @image is NULL, free @ptr, otherwise do nothing.
438 image_g_free (MonoImage *image, gpointer ptr)
444 #ifndef DISABLE_REFLECTION_EMIT
446 image_strdup (MonoImage *image, const char *s)
448 MONO_REQ_GC_NEUTRAL_MODE;
451 return mono_image_strdup (image, s);
457 #define image_g_new(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
460 #define image_g_new0(image,struct_type, n_structs) \
461 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
465 alloc_table (MonoDynamicTable *table, guint nrows)
467 MONO_REQ_GC_NEUTRAL_MODE;
470 g_assert (table->columns);
471 if (nrows + 1 >= table->alloc_rows) {
472 while (nrows + 1 >= table->alloc_rows) {
473 if (table->alloc_rows == 0)
474 table->alloc_rows = 16;
476 table->alloc_rows *= 2;
479 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
484 make_room_in_stream (MonoDynamicStream *stream, int size)
486 MONO_REQ_GC_NEUTRAL_MODE;
488 if (size <= stream->alloc_size)
491 while (stream->alloc_size <= size) {
492 if (stream->alloc_size < 4096)
493 stream->alloc_size = 4096;
495 stream->alloc_size *= 2;
498 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
504 MONO_REQ_GC_NEUTRAL_MODE;
508 gpointer oldkey, oldval;
510 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511 return GPOINTER_TO_UINT (oldval);
513 len = strlen (str) + 1;
516 make_room_in_stream (sh, idx + len);
519 * We strdup the string even if we already copy them in sh->data
520 * so that the string pointers in the hash remain valid even if
521 * we need to realloc sh->data. We may want to avoid that later.
523 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524 memcpy (sh->data + idx, str, len);
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
532 MONO_REQ_GC_UNSAFE_MODE;
534 mono_error_init (error);
535 char *name = mono_string_to_utf8_checked (str, error);
536 return_val_if_nok (error, -1);
538 idx = string_heap_insert (sh, name);
543 #ifndef DISABLE_REFLECTION_EMIT
545 string_heap_init (MonoDynamicStream *sh)
547 MONO_REQ_GC_NEUTRAL_MODE;
550 sh->alloc_size = 4096;
551 sh->data = (char *)g_malloc (4096);
552 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
553 string_heap_insert (sh, "");
558 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
560 MONO_REQ_GC_NEUTRAL_MODE;
564 make_room_in_stream (stream, stream->index + len);
565 memcpy (stream->data + stream->index, data, len);
567 stream->index += len;
569 * align index? Not without adding an additional param that controls it since
570 * we may store a blob value in pieces.
576 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
578 MONO_REQ_GC_NEUTRAL_MODE;
582 make_room_in_stream (stream, stream->index + len);
583 memset (stream->data + stream->index, 0, len);
585 stream->index += len;
590 stream_data_align (MonoDynamicStream *stream)
592 MONO_REQ_GC_NEUTRAL_MODE;
595 guint32 count = stream->index % 4;
597 /* we assume the stream data will be aligned */
599 mono_image_add_stream_data (stream, buf, 4 - count);
602 #ifndef DISABLE_REFLECTION_EMIT
604 mono_blob_entry_hash (const char* str)
606 MONO_REQ_GC_NEUTRAL_MODE;
610 len = mono_metadata_decode_blob_size (str, &str);
614 for (str += 1; str < end; str++)
615 h = (h << 5) - h + *str;
623 mono_blob_entry_equal (const char *str1, const char *str2) {
624 MONO_REQ_GC_NEUTRAL_MODE;
629 len = mono_metadata_decode_blob_size (str1, &end1);
630 len2 = mono_metadata_decode_blob_size (str2, &end2);
633 return memcmp (end1, end2, len) == 0;
637 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
639 MONO_REQ_GC_NEUTRAL_MODE;
643 gpointer oldkey, oldval;
645 copy = (char *)g_malloc (s1+s2);
646 memcpy (copy, b1, s1);
647 memcpy (copy + s1, b2, s2);
648 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
650 idx = GPOINTER_TO_UINT (oldval);
652 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
653 mono_image_add_stream_data (&assembly->blob, b2, s2);
654 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
660 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
662 MONO_REQ_GC_NEUTRAL_MODE;
666 guint32 size = buf->p - buf->buf;
668 g_assert (size <= (buf->end - buf->buf));
669 mono_metadata_encode_value (size, b, &b);
670 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
674 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
675 * dest may be misaligned.
678 swap_with_size (char *dest, const char* val, int len, int nelem) {
679 MONO_REQ_GC_NEUTRAL_MODE;
680 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
683 for (elem = 0; elem < nelem; ++elem) {
709 g_assert_not_reached ();
715 memcpy (dest, val, len * nelem);
720 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
722 MONO_REQ_GC_UNSAFE_MODE;
726 guint32 idx = 0, len;
728 len = str->length * 2;
729 mono_metadata_encode_value (len, b, &b);
730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
732 char *swapped = g_malloc (2 * mono_string_length (str));
733 const char *p = (const char*)mono_string_chars (str);
735 swap_with_size (swapped, p, 2, mono_string_length (str));
736 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
740 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
745 #ifndef DISABLE_REFLECTION_EMIT
747 default_class_from_mono_type (MonoType *type)
749 MONO_REQ_GC_NEUTRAL_MODE;
751 switch (type->type) {
752 case MONO_TYPE_OBJECT:
753 return mono_defaults.object_class;
755 return mono_defaults.void_class;
756 case MONO_TYPE_BOOLEAN:
757 return mono_defaults.boolean_class;
759 return mono_defaults.char_class;
761 return mono_defaults.sbyte_class;
763 return mono_defaults.byte_class;
765 return mono_defaults.int16_class;
767 return mono_defaults.uint16_class;
769 return mono_defaults.int32_class;
771 return mono_defaults.uint32_class;
773 return mono_defaults.int_class;
775 return mono_defaults.uint_class;
777 return mono_defaults.int64_class;
779 return mono_defaults.uint64_class;
781 return mono_defaults.single_class;
783 return mono_defaults.double_class;
784 case MONO_TYPE_STRING:
785 return mono_defaults.string_class;
787 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
788 g_assert_not_reached ();
796 * mono_class_get_ref_info:
798 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
801 mono_class_get_ref_info (MonoClass *klass)
803 MONO_REQ_GC_UNSAFE_MODE;
805 if (klass->ref_info_handle == 0)
808 return mono_gchandle_get_target (klass->ref_info_handle);
812 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
814 MONO_REQ_GC_UNSAFE_MODE;
816 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
817 g_assert (klass->ref_info_handle != 0);
821 mono_class_free_ref_info (MonoClass *klass)
823 MONO_REQ_GC_NEUTRAL_MODE;
825 if (klass->ref_info_handle) {
826 mono_gchandle_free (klass->ref_info_handle);
827 klass->ref_info_handle = 0;
832 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
834 MONO_REQ_GC_NEUTRAL_MODE;
837 MonoGenericInst *class_inst;
842 class_inst = gclass->context.class_inst;
844 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
845 klass = gclass->container_class;
846 sigbuffer_add_value (buf, klass->byval_arg.type);
847 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
849 sigbuffer_add_value (buf, class_inst->type_argc);
850 for (i = 0; i < class_inst->type_argc; ++i)
851 encode_type (assembly, class_inst->type_argv [i], buf);
856 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
858 MONO_REQ_GC_NEUTRAL_MODE;
861 g_assert_not_reached ();
866 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
870 case MONO_TYPE_BOOLEAN:
884 case MONO_TYPE_STRING:
885 case MONO_TYPE_OBJECT:
886 case MONO_TYPE_TYPEDBYREF:
887 sigbuffer_add_value (buf, type->type);
890 sigbuffer_add_value (buf, type->type);
891 encode_type (assembly, type->data.type, buf);
893 case MONO_TYPE_SZARRAY:
894 sigbuffer_add_value (buf, type->type);
895 encode_type (assembly, &type->data.klass->byval_arg, buf);
897 case MONO_TYPE_VALUETYPE:
898 case MONO_TYPE_CLASS: {
899 MonoClass *k = mono_class_from_mono_type (type);
901 if (k->generic_container) {
902 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
903 encode_generic_class (assembly, gclass, buf);
906 * Make sure we use the correct type.
908 sigbuffer_add_value (buf, k->byval_arg.type);
910 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
911 * otherwise two typerefs could point to the same type, leading to
912 * verification errors.
914 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
918 case MONO_TYPE_ARRAY:
919 sigbuffer_add_value (buf, type->type);
920 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
921 sigbuffer_add_value (buf, type->data.array->rank);
922 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
923 sigbuffer_add_value (buf, 0);
925 case MONO_TYPE_GENERICINST:
926 encode_generic_class (assembly, type->data.generic_class, buf);
930 sigbuffer_add_value (buf, type->type);
931 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
934 g_error ("need to encode type %x", type->type);
939 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
941 MONO_REQ_GC_UNSAFE_MODE;
943 mono_error_init (error);
946 sigbuffer_add_value (buf, MONO_TYPE_VOID);
950 MonoType *t = mono_reflection_type_get_handle (type, error);
951 return_if_nok (error);
952 encode_type (assembly, t, buf);
956 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
958 MONO_REQ_GC_UNSAFE_MODE;
962 mono_error_init (error);
965 for (i = 0; i < mono_array_length (modreq); ++i) {
966 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
967 return_if_nok (error);
968 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
969 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
973 for (i = 0; i < mono_array_length (modopt); ++i) {
974 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
975 return_if_nok (error);
976 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
977 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
982 #ifndef DISABLE_REFLECTION_EMIT
984 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
986 MONO_REQ_GC_UNSAFE_MODE;
990 guint32 nparams = sig->param_count;
996 sigbuffer_init (&buf, 32);
998 * FIXME: vararg, explicit_this, differenc call_conv values...
1000 idx = sig->call_convention;
1002 idx |= 0x20; /* hasthis */
1003 if (sig->generic_param_count)
1004 idx |= 0x10; /* generic */
1005 sigbuffer_add_byte (&buf, idx);
1006 if (sig->generic_param_count)
1007 sigbuffer_add_value (&buf, sig->generic_param_count);
1008 sigbuffer_add_value (&buf, nparams);
1009 encode_type (assembly, sig->ret, &buf);
1010 for (i = 0; i < nparams; ++i) {
1011 if (i == sig->sentinelpos)
1012 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1013 encode_type (assembly, sig->params [i], &buf);
1015 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1016 sigbuffer_free (&buf);
1022 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1024 MONO_REQ_GC_UNSAFE_MODE;
1026 mono_error_init (error);
1029 * FIXME: reuse code from method_encode_signature().
1033 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1034 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1035 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1038 sigbuffer_init (&buf, 32);
1039 /* LAMESPEC: all the call conv spec is foobared */
1040 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1041 if (mb->call_conv & 2)
1042 idx |= 0x5; /* vararg */
1043 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1044 idx |= 0x20; /* hasthis */
1046 idx |= 0x10; /* generic */
1047 sigbuffer_add_byte (&buf, idx);
1049 sigbuffer_add_value (&buf, ngparams);
1050 sigbuffer_add_value (&buf, nparams + notypes);
1051 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1054 encode_reflection_type (assembly, mb->rtype, &buf, error);
1057 for (i = 0; i < nparams; ++i) {
1058 MonoArray *modreq = NULL;
1059 MonoArray *modopt = NULL;
1060 MonoReflectionType *pt;
1062 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1063 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1064 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1065 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1066 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1069 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1070 encode_reflection_type (assembly, pt, &buf, error);
1075 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1076 for (i = 0; i < notypes; ++i) {
1077 MonoReflectionType *pt;
1079 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1080 encode_reflection_type (assembly, pt, &buf, error);
1085 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1087 sigbuffer_free (&buf);
1092 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1094 MONO_REQ_GC_UNSAFE_MODE;
1096 mono_error_init (error);
1098 MonoDynamicTable *table;
1100 guint32 idx, sig_idx;
1101 guint nl = mono_array_length (ilgen->locals);
1105 sigbuffer_init (&buf, 32);
1106 sigbuffer_add_value (&buf, 0x07);
1107 sigbuffer_add_value (&buf, nl);
1108 for (i = 0; i < nl; ++i) {
1109 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1112 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1114 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1115 if (!is_ok (error)) {
1116 sigbuffer_free (&buf);
1120 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1121 sigbuffer_free (&buf);
1123 if (assembly->standalonesig_cache == NULL)
1124 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1125 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1129 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1130 idx = table->next_idx ++;
1132 alloc_table (table, table->rows);
1133 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1135 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1137 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1143 method_count_clauses (MonoReflectionILGen *ilgen)
1145 MONO_REQ_GC_UNSAFE_MODE;
1147 guint32 num_clauses = 0;
1150 MonoILExceptionInfo *ex_info;
1151 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1152 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1153 if (ex_info->handlers)
1154 num_clauses += mono_array_length (ex_info->handlers);
1162 #ifndef DISABLE_REFLECTION_EMIT
1163 static MonoExceptionClause*
1164 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1166 MONO_REQ_GC_UNSAFE_MODE;
1168 mono_error_init (error);
1170 MonoExceptionClause *clauses;
1171 MonoExceptionClause *clause;
1172 MonoILExceptionInfo *ex_info;
1173 MonoILExceptionBlock *ex_block;
1174 guint32 finally_start;
1175 int i, j, clause_index;;
1177 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1180 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1181 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1182 finally_start = ex_info->start + ex_info->len;
1183 if (!ex_info->handlers)
1185 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1186 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1187 clause = &(clauses [clause_index]);
1189 clause->flags = ex_block->type;
1190 clause->try_offset = ex_info->start;
1192 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1193 clause->try_len = finally_start - ex_info->start;
1195 clause->try_len = ex_info->len;
1196 clause->handler_offset = ex_block->start;
1197 clause->handler_len = ex_block->len;
1198 if (ex_block->extype) {
1199 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1201 if (!is_ok (error)) {
1202 image_g_free (image, clauses);
1205 clause->data.catch_class = mono_class_from_mono_type (extype);
1207 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1208 clause->data.filter_offset = ex_block->filter_offset;
1210 clause->data.filter_offset = 0;
1212 finally_start = ex_block->start + ex_block->len;
1220 #endif /* !DISABLE_REFLECTION_EMIT */
1223 * method_encode_code:
1225 * @assembly the assembly
1226 * @mb the managed MethodBuilder
1227 * @error set on error
1229 * Note that the return value is not sensible if @error is set.
1232 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1234 MONO_REQ_GC_UNSAFE_MODE;
1239 gint32 max_stack, i;
1240 gint32 num_locals = 0;
1241 gint32 num_exception = 0;
1244 char fat_header [12];
1246 guint16 short_value;
1247 guint32 local_sig = 0;
1248 guint32 header_size = 12;
1251 mono_error_init (error);
1253 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1254 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1258 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1260 code = mb->ilgen->code;
1261 code_size = mb->ilgen->code_len;
1262 max_stack = mb->ilgen->max_stack;
1263 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1264 if (mb->ilgen->ex_handlers)
1265 num_exception = method_count_clauses (mb->ilgen);
1269 MonoError inner_error;
1270 char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
1271 if (!is_ok (&inner_error)) {
1272 name = g_strdup ("");
1273 mono_error_cleanup (&inner_error);
1275 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1276 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1282 code_size = mono_array_length (code);
1283 max_stack = 8; /* we probably need to run a verifier on the code... */
1286 stream_data_align (&assembly->code);
1288 /* check for exceptions, maxstack, locals */
1289 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1291 if (code_size < 64 && !(code_size & 1)) {
1292 flags = (code_size << 2) | 0x2;
1293 } else if (code_size < 32 && (code_size & 1)) {
1294 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1298 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1299 /* add to the fixup todo list */
1300 if (mb->ilgen && mb->ilgen->num_token_fixups)
1301 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1302 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1303 return assembly->text_rva + idx;
1307 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1308 return_val_if_nok (error, 0);
1311 * FIXME: need to set also the header size in fat_flags.
1312 * (and more sects and init locals flags)
1316 fat_flags |= METHOD_HEADER_MORE_SECTS;
1317 if (mb->init_locals)
1318 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1319 fat_header [0] = fat_flags;
1320 fat_header [1] = (header_size / 4 ) << 4;
1321 short_value = GUINT16_TO_LE (max_stack);
1322 memcpy (fat_header + 2, &short_value, 2);
1323 int_value = GUINT32_TO_LE (code_size);
1324 memcpy (fat_header + 4, &int_value, 4);
1325 int_value = GUINT32_TO_LE (local_sig);
1326 memcpy (fat_header + 8, &int_value, 4);
1327 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1328 /* add to the fixup todo list */
1329 if (mb->ilgen && mb->ilgen->num_token_fixups)
1330 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1332 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1333 if (num_exception) {
1334 unsigned char sheader [4];
1335 MonoILExceptionInfo * ex_info;
1336 MonoILExceptionBlock * ex_block;
1339 stream_data_align (&assembly->code);
1340 /* always use fat format for now */
1341 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1342 num_exception *= 6 * sizeof (guint32);
1343 num_exception += 4; /* include the size of the header */
1344 sheader [1] = num_exception & 0xff;
1345 sheader [2] = (num_exception >> 8) & 0xff;
1346 sheader [3] = (num_exception >> 16) & 0xff;
1347 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1348 /* fat header, so we are already aligned */
1350 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1351 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1352 if (ex_info->handlers) {
1353 int finally_start = ex_info->start + ex_info->len;
1354 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1356 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1358 val = GUINT32_TO_LE (ex_block->type);
1359 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1361 val = GUINT32_TO_LE (ex_info->start);
1362 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1363 /* need fault, too, probably */
1364 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1365 val = GUINT32_TO_LE (finally_start - ex_info->start);
1367 val = GUINT32_TO_LE (ex_info->len);
1368 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1369 /* handler offset */
1370 val = GUINT32_TO_LE (ex_block->start);
1371 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1373 val = GUINT32_TO_LE (ex_block->len);
1374 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1375 finally_start = ex_block->start + ex_block->len;
1376 if (ex_block->extype) {
1377 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1378 return_val_if_nok (error, 0);
1380 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1382 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1383 val = ex_block->filter_offset;
1387 val = GUINT32_TO_LE (val);
1388 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1389 /*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",
1390 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);*/
1393 g_error ("No clauses for ex info block %d", i);
1397 return assembly->text_rva + idx;
1401 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1403 MONO_REQ_GC_NEUTRAL_MODE;
1406 MonoDynamicTable *table;
1409 table = &assembly->tables [table_idx];
1411 g_assert (col < table->columns);
1413 values = table->values + table->columns;
1414 for (i = 1; i <= table->rows; ++i) {
1415 if (values [col] == token)
1417 values += table->columns;
1423 * LOCKING: Acquires the loader lock.
1425 static MonoCustomAttrInfo*
1426 lookup_custom_attr (MonoImage *image, gpointer member)
1428 MONO_REQ_GC_NEUTRAL_MODE;
1430 MonoCustomAttrInfo* res;
1432 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1437 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1443 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1445 MONO_REQ_GC_UNSAFE_MODE;
1447 /* FIXME: Need to do more checks */
1448 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1449 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1451 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1458 static MonoCustomAttrInfo*
1459 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1461 MONO_REQ_GC_UNSAFE_MODE;
1463 int i, index, count, not_visible;
1464 MonoCustomAttrInfo *ainfo;
1465 MonoReflectionCustomAttr *cattr;
1469 /* FIXME: check in assembly the Run flag is set */
1471 count = mono_array_length (cattrs);
1473 /* Skip nonpublic attributes since MS.NET seems to do the same */
1474 /* FIXME: This needs to be done more globally */
1476 for (i = 0; i < count; ++i) {
1477 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1478 if (!custom_attr_visible (image, cattr))
1481 count -= not_visible;
1483 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1485 ainfo->image = image;
1486 ainfo->num_attrs = count;
1487 ainfo->cached = alloc_img != NULL;
1489 for (i = 0; i < count; ++i) {
1490 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1491 if (custom_attr_visible (image, cattr)) {
1492 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1493 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1494 ainfo->attrs [index].ctor = cattr->ctor->method;
1495 ainfo->attrs [index].data = saved;
1496 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1504 #ifndef DISABLE_REFLECTION_EMIT
1506 * LOCKING: Acquires the loader lock.
1509 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1511 MONO_REQ_GC_UNSAFE_MODE;
1513 MonoCustomAttrInfo *ainfo, *tmp;
1515 if (!cattrs || !mono_array_length (cattrs))
1518 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1520 mono_loader_lock ();
1521 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1523 mono_custom_attrs_free (tmp);
1524 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1525 mono_loader_unlock ();
1531 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1533 MONO_REQ_GC_NEUTRAL_MODE;
1535 if (ainfo && !ainfo->cached)
1540 * idx is the table index of the object
1541 * type is one of MONO_CUSTOM_ATTR_*
1544 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1546 MONO_REQ_GC_UNSAFE_MODE;
1548 MonoDynamicTable *table;
1549 MonoReflectionCustomAttr *cattr;
1551 guint32 count, i, token;
1553 char *p = blob_size;
1555 mono_error_init (error);
1557 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1560 count = mono_array_length (cattrs);
1561 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1562 table->rows += count;
1563 alloc_table (table, table->rows);
1564 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1565 idx <<= MONO_CUSTOM_ATTR_BITS;
1567 for (i = 0; i < count; ++i) {
1568 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1569 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1570 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1571 if (!mono_error_ok (error)) goto fail;
1572 type = mono_metadata_token_index (token);
1573 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1574 switch (mono_metadata_token_table (token)) {
1575 case MONO_TABLE_METHOD:
1576 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1578 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1579 * method, not the one returned by mono_image_create_token ().
1581 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1583 case MONO_TABLE_MEMBERREF:
1584 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1587 g_warning ("got wrong token in custom attr");
1590 values [MONO_CUSTOM_ATTR_TYPE] = type;
1592 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1593 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1594 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1595 values += MONO_CUSTOM_ATTR_SIZE;
1606 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1608 MONO_REQ_GC_UNSAFE_MODE;
1610 MonoDynamicTable *table;
1612 guint32 count, i, idx;
1613 MonoReflectionPermissionSet *perm;
1618 count = mono_array_length (permissions);
1619 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1620 table->rows += count;
1621 alloc_table (table, table->rows);
1623 for (i = 0; i < mono_array_length (permissions); ++i) {
1624 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1626 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1628 idx = mono_metadata_token_index (parent_token);
1629 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1630 switch (mono_metadata_token_table (parent_token)) {
1631 case MONO_TABLE_TYPEDEF:
1632 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1634 case MONO_TABLE_METHOD:
1635 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1637 case MONO_TABLE_ASSEMBLY:
1638 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1641 g_assert_not_reached ();
1644 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1645 values [MONO_DECL_SECURITY_PARENT] = idx;
1646 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1653 * Fill in the MethodDef and ParamDef tables for a method.
1654 * This is used for both normal methods and constructors.
1657 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1659 MONO_REQ_GC_UNSAFE_MODE;
1661 MonoDynamicTable *table;
1665 mono_error_init (error);
1667 /* room in this table is already allocated */
1668 table = &assembly->tables [MONO_TABLE_METHOD];
1669 *mb->table_idx = table->next_idx ++;
1670 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1671 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1672 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1673 return_val_if_nok (error, FALSE);
1674 values [MONO_METHOD_FLAGS] = mb->attrs;
1675 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1676 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1677 return_val_if_nok (error, FALSE);
1678 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1679 return_val_if_nok (error, FALSE);
1681 table = &assembly->tables [MONO_TABLE_PARAM];
1682 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1684 mono_image_add_decl_security (assembly,
1685 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1688 MonoDynamicTable *mtable;
1691 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1692 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1695 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1696 if (mono_array_get (mb->pinfo, gpointer, i))
1699 table->rows += count;
1700 alloc_table (table, table->rows);
1701 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1702 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1703 MonoReflectionParamBuilder *pb;
1704 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1705 values [MONO_PARAM_FLAGS] = pb->attrs;
1706 values [MONO_PARAM_SEQUENCE] = i;
1707 if (pb->name != NULL) {
1708 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
1709 return_val_if_nok (error, FALSE);
1711 values [MONO_PARAM_NAME] = 0;
1713 values += MONO_PARAM_SIZE;
1714 if (pb->marshal_info) {
1716 alloc_table (mtable, mtable->rows);
1717 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1718 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1719 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1720 return_val_if_nok (error, FALSE);
1722 pb->table_idx = table->next_idx++;
1723 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1724 guint32 field_type = 0;
1725 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1727 alloc_table (mtable, mtable->rows);
1728 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1729 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1730 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1731 mvalues [MONO_CONSTANT_TYPE] = field_type;
1732 mvalues [MONO_CONSTANT_PADDING] = 0;
1741 #ifndef DISABLE_REFLECTION_EMIT
1743 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1745 MONO_REQ_GC_UNSAFE_MODE;
1747 mono_error_init (error);
1748 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1750 rmb->ilgen = mb->ilgen;
1751 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1752 return_val_if_nok (error, FALSE);
1753 rmb->parameters = mb->parameters;
1754 rmb->generic_params = mb->generic_params;
1755 rmb->generic_container = mb->generic_container;
1756 rmb->opt_types = NULL;
1757 rmb->pinfo = mb->pinfo;
1758 rmb->attrs = mb->attrs;
1759 rmb->iattrs = mb->iattrs;
1760 rmb->call_conv = mb->call_conv;
1761 rmb->code = mb->code;
1762 rmb->type = mb->type;
1763 rmb->name = mb->name;
1764 rmb->table_idx = &mb->table_idx;
1765 rmb->init_locals = mb->init_locals;
1766 rmb->skip_visibility = FALSE;
1767 rmb->return_modreq = mb->return_modreq;
1768 rmb->return_modopt = mb->return_modopt;
1769 rmb->param_modreq = mb->param_modreq;
1770 rmb->param_modopt = mb->param_modopt;
1771 rmb->permissions = mb->permissions;
1772 rmb->mhandle = mb->mhandle;
1777 rmb->charset = mb->charset;
1778 rmb->extra_flags = mb->extra_flags;
1779 rmb->native_cc = mb->native_cc;
1780 rmb->dllentry = mb->dllentry;
1788 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1790 MONO_REQ_GC_UNSAFE_MODE;
1792 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1794 mono_error_init (error);
1796 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1798 rmb->ilgen = mb->ilgen;
1799 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1800 return_val_if_nok (error, FALSE);
1801 rmb->parameters = mb->parameters;
1802 rmb->generic_params = NULL;
1803 rmb->generic_container = NULL;
1804 rmb->opt_types = NULL;
1805 rmb->pinfo = mb->pinfo;
1806 rmb->attrs = mb->attrs;
1807 rmb->iattrs = mb->iattrs;
1808 rmb->call_conv = mb->call_conv;
1810 rmb->type = mb->type;
1811 rmb->name = mono_string_new (mono_domain_get (), name);
1812 rmb->table_idx = &mb->table_idx;
1813 rmb->init_locals = mb->init_locals;
1814 rmb->skip_visibility = FALSE;
1815 rmb->return_modreq = NULL;
1816 rmb->return_modopt = NULL;
1817 rmb->param_modreq = mb->param_modreq;
1818 rmb->param_modopt = mb->param_modopt;
1819 rmb->permissions = mb->permissions;
1820 rmb->mhandle = mb->mhandle;
1828 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1830 MONO_REQ_GC_UNSAFE_MODE;
1832 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1834 rmb->ilgen = mb->ilgen;
1835 rmb->rtype = mb->rtype;
1836 rmb->parameters = mb->parameters;
1837 rmb->generic_params = NULL;
1838 rmb->generic_container = NULL;
1839 rmb->opt_types = NULL;
1841 rmb->attrs = mb->attrs;
1843 rmb->call_conv = mb->call_conv;
1845 rmb->type = (MonoObject *) mb->owner;
1846 rmb->name = mb->name;
1847 rmb->table_idx = NULL;
1848 rmb->init_locals = mb->init_locals;
1849 rmb->skip_visibility = mb->skip_visibility;
1850 rmb->return_modreq = NULL;
1851 rmb->return_modopt = NULL;
1852 rmb->param_modreq = NULL;
1853 rmb->param_modopt = NULL;
1854 rmb->permissions = NULL;
1855 rmb->mhandle = mb->mhandle;
1862 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1864 MONO_REQ_GC_UNSAFE_MODE;
1866 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1867 MonoDynamicTable *table;
1870 MonoReflectionMethod *m;
1873 mono_error_init (error);
1875 if (!mb->override_methods)
1878 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1879 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1881 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1883 alloc_table (table, table->rows);
1884 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1885 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1886 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1888 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1889 return_val_if_nok (error, FALSE);
1891 switch (mono_metadata_token_table (tok)) {
1892 case MONO_TABLE_MEMBERREF:
1893 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1895 case MONO_TABLE_METHOD:
1896 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1899 g_assert_not_reached ();
1901 values [MONO_METHODIMPL_DECLARATION] = tok;
1907 #ifndef DISABLE_REFLECTION_EMIT
1909 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1911 MONO_REQ_GC_UNSAFE_MODE;
1913 MonoDynamicTable *table;
1915 ReflectionMethodBuilder rmb;
1918 mono_error_init (error);
1920 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1921 !mono_image_basic_method (&rmb, assembly, error))
1924 mb->table_idx = *rmb.table_idx;
1926 if (mb->dll) { /* It's a P/Invoke method */
1928 /* map CharSet values to on-disk values */
1929 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1930 int extra_flags = mb->extra_flags;
1931 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1933 alloc_table (table, table->rows);
1934 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1936 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1937 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1939 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
1940 return_val_if_nok (error, FALSE);
1942 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1943 return_val_if_nok (error, FALSE);
1945 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
1946 return_val_if_nok (error, FALSE);
1947 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1948 table = &assembly->tables [MONO_TABLE_MODULEREF];
1950 alloc_table (table, table->rows);
1951 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1952 values [MONO_IMPLMAP_SCOPE] = table->rows;
1956 if (mb->generic_params) {
1957 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1958 table->rows += mono_array_length (mb->generic_params);
1959 alloc_table (table, table->rows);
1960 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1961 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1963 mono_image_get_generic_param_info (
1964 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1972 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1974 MONO_REQ_GC_UNSAFE_MODE;
1976 ReflectionMethodBuilder rmb;
1978 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1981 if (!mono_image_basic_method (&rmb, assembly, error))
1984 mb->table_idx = *rmb.table_idx;
1991 type_get_fully_qualified_name (MonoType *type)
1993 MONO_REQ_GC_NEUTRAL_MODE;
1995 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1999 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
2001 MONO_REQ_GC_UNSAFE_MODE;
2006 klass = mono_class_from_mono_type (type);
2008 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2009 ta = klass->image->assembly;
2010 if (assembly_is_dynamic (ta) || (ta == ass)) {
2011 if (klass->generic_class || klass->generic_container)
2012 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2013 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2015 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2018 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2021 #ifndef DISABLE_REFLECTION_EMIT
2022 /*field_image is the image to which the eventual custom mods have been encoded against*/
2024 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2026 MONO_REQ_GC_NEUTRAL_MODE;
2029 guint32 idx, i, token;
2031 if (!assembly->save)
2034 sigbuffer_init (&buf, 32);
2036 sigbuffer_add_value (&buf, 0x06);
2037 /* encode custom attributes before the type */
2038 if (type->num_mods) {
2039 for (i = 0; i < type->num_mods; ++i) {
2042 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2043 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2045 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2047 token = type->modifiers [i].token;
2050 if (type->modifiers [i].required)
2051 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2053 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2055 sigbuffer_add_value (&buf, token);
2058 encode_type (assembly, type, &buf);
2059 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2060 sigbuffer_free (&buf);
2066 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2068 MONO_REQ_GC_UNSAFE_MODE;
2070 mono_error_init (error);
2074 guint32 typespec = 0;
2078 init_type_builder_generics (fb->type, error);
2079 return_val_if_nok (error, 0);
2081 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2082 return_val_if_nok (error, 0);
2083 klass = mono_class_from_mono_type (type);
2085 sigbuffer_init (&buf, 32);
2087 sigbuffer_add_value (&buf, 0x06);
2088 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2091 /* encode custom attributes before the type */
2093 if (klass->generic_container)
2094 typespec = create_typespec (assembly, type);
2097 MonoGenericClass *gclass;
2098 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2099 encode_generic_class (assembly, gclass, &buf);
2101 encode_type (assembly, type, &buf);
2103 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2104 sigbuffer_free (&buf);
2107 sigbuffer_free (&buf);
2112 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2114 MONO_REQ_GC_UNSAFE_MODE;
2116 char blob_size [64];
2117 char *b = blob_size;
2120 guint32 idx = 0, len = 0, dummy = 0;
2122 buf = (char *)g_malloc (64);
2124 *ret_type = MONO_TYPE_CLASS;
2126 box_val = (char*)&dummy;
2128 box_val = ((char*)val) + sizeof (MonoObject);
2129 *ret_type = val->vtable->klass->byval_arg.type;
2132 switch (*ret_type) {
2133 case MONO_TYPE_BOOLEAN:
2138 case MONO_TYPE_CHAR:
2155 case MONO_TYPE_VALUETYPE: {
2156 MonoClass *klass = val->vtable->klass;
2158 if (klass->enumtype) {
2159 *ret_type = mono_class_enum_basetype (klass)->type;
2161 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2164 g_error ("we can't encode valuetypes, we should have never reached this line");
2167 case MONO_TYPE_CLASS:
2169 case MONO_TYPE_STRING: {
2170 MonoString *str = (MonoString*)val;
2171 /* there is no signature */
2172 len = str->length * 2;
2173 mono_metadata_encode_value (len, b, &b);
2174 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2176 char *swapped = g_malloc (2 * mono_string_length (str));
2177 const char *p = (const char*)mono_string_chars (str);
2179 swap_with_size (swapped, p, 2, mono_string_length (str));
2180 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2184 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2190 case MONO_TYPE_GENERICINST:
2191 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2194 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2197 /* there is no signature */
2198 mono_metadata_encode_value (len, b, &b);
2199 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2200 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2201 swap_with_size (blob_size, box_val, len, 1);
2202 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2204 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2212 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2214 MONO_REQ_GC_UNSAFE_MODE;
2216 mono_error_init (error);
2222 sigbuffer_init (&buf, 32);
2224 sigbuffer_add_value (&buf, minfo->type);
2226 switch (minfo->type) {
2227 case MONO_NATIVE_BYVALTSTR:
2228 case MONO_NATIVE_BYVALARRAY:
2229 sigbuffer_add_value (&buf, minfo->count);
2231 case MONO_NATIVE_LPARRAY:
2232 if (minfo->eltype || minfo->has_size) {
2233 sigbuffer_add_value (&buf, minfo->eltype);
2234 if (minfo->has_size) {
2235 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2236 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2238 /* LAMESPEC: ElemMult is undocumented */
2239 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2243 case MONO_NATIVE_SAFEARRAY:
2245 sigbuffer_add_value (&buf, minfo->eltype);
2247 case MONO_NATIVE_CUSTOM:
2249 str = mono_string_to_utf8_checked (minfo->guid, error);
2250 if (!is_ok (error)) {
2251 sigbuffer_free (&buf);
2255 sigbuffer_add_value (&buf, len);
2256 sigbuffer_add_mem (&buf, str, len);
2259 sigbuffer_add_value (&buf, 0);
2261 /* native type name */
2262 sigbuffer_add_value (&buf, 0);
2263 /* custom marshaler type name */
2264 if (minfo->marshaltype || minfo->marshaltyperef) {
2265 if (minfo->marshaltyperef) {
2266 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2267 if (!is_ok (error)) {
2268 sigbuffer_free (&buf);
2271 str = type_get_fully_qualified_name (marshaltype);
2273 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2274 if (!is_ok (error)) {
2275 sigbuffer_free (&buf);
2280 sigbuffer_add_value (&buf, len);
2281 sigbuffer_add_mem (&buf, str, len);
2284 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2285 sigbuffer_add_value (&buf, 0);
2287 if (minfo->mcookie) {
2288 str = mono_string_to_utf8_checked (minfo->mcookie, error);
2289 if (!is_ok (error)) {
2290 sigbuffer_free (&buf);
2294 sigbuffer_add_value (&buf, len);
2295 sigbuffer_add_mem (&buf, str, len);
2298 sigbuffer_add_value (&buf, 0);
2304 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2305 sigbuffer_free (&buf);
2310 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2312 MONO_REQ_GC_UNSAFE_MODE;
2314 mono_error_init (error);
2316 MonoDynamicTable *table;
2319 /* maybe this fixup should be done in the C# code */
2320 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2321 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2322 table = &assembly->tables [MONO_TABLE_FIELD];
2323 fb->table_idx = table->next_idx ++;
2324 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2325 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2326 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
2327 return_if_nok (error);
2328 values [MONO_FIELD_FLAGS] = fb->attrs;
2329 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2330 return_if_nok (error);
2333 if (fb->offset != -1) {
2334 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2336 alloc_table (table, table->rows);
2337 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2338 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2339 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2341 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2342 MonoTypeEnum field_type = (MonoTypeEnum)0;
2343 table = &assembly->tables [MONO_TABLE_CONSTANT];
2345 alloc_table (table, table->rows);
2346 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2347 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2348 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2349 values [MONO_CONSTANT_TYPE] = field_type;
2350 values [MONO_CONSTANT_PADDING] = 0;
2352 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2354 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2356 alloc_table (table, table->rows);
2357 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2358 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2360 * We store it in the code section because it's simpler for now.
2363 if (mono_array_length (fb->rva_data) >= 10)
2364 stream_data_align (&assembly->code);
2365 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2367 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2368 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2370 if (fb->marshal_info) {
2371 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2373 alloc_table (table, table->rows);
2374 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2375 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2376 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2377 return_if_nok (error);
2382 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2384 MONO_REQ_GC_UNSAFE_MODE;
2386 mono_error_init (error);
2389 guint32 nparams = 0;
2390 MonoReflectionMethodBuilder *mb = fb->get_method;
2391 MonoReflectionMethodBuilder *smb = fb->set_method;
2394 if (mb && mb->parameters)
2395 nparams = mono_array_length (mb->parameters);
2396 if (!mb && smb && smb->parameters)
2397 nparams = mono_array_length (smb->parameters) - 1;
2398 sigbuffer_init (&buf, 32);
2399 if (fb->call_conv & 0x20)
2400 sigbuffer_add_byte (&buf, 0x28);
2402 sigbuffer_add_byte (&buf, 0x08);
2403 sigbuffer_add_value (&buf, nparams);
2405 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2408 for (i = 0; i < nparams; ++i) {
2409 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2410 encode_reflection_type (assembly, pt, &buf, error);
2414 } else if (smb && smb->parameters) {
2415 /* the property type is the last param */
2416 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2420 for (i = 0; i < nparams; ++i) {
2421 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2422 encode_reflection_type (assembly, pt, &buf, error);
2427 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2432 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2433 sigbuffer_free (&buf);
2436 sigbuffer_free (&buf);
2441 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2443 MONO_REQ_GC_UNSAFE_MODE;
2445 mono_error_init (error);
2447 MonoDynamicTable *table;
2449 guint num_methods = 0;
2453 * we need to set things in the following tables:
2454 * PROPERTYMAP (info already filled in _get_type_info ())
2455 * PROPERTY (rows already preallocated in _get_type_info ())
2456 * METHOD (method info already done with the generic method code)
2460 table = &assembly->tables [MONO_TABLE_PROPERTY];
2461 pb->table_idx = table->next_idx ++;
2462 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2463 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
2464 return_if_nok (error);
2465 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2466 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2467 return_if_nok (error);
2470 /* FIXME: we still don't handle 'other' methods */
2471 if (pb->get_method) num_methods ++;
2472 if (pb->set_method) num_methods ++;
2474 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2475 table->rows += num_methods;
2476 alloc_table (table, table->rows);
2478 if (pb->get_method) {
2479 semaidx = table->next_idx ++;
2480 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2481 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2482 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2483 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2485 if (pb->set_method) {
2486 semaidx = table->next_idx ++;
2487 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2488 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2489 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2490 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2492 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2493 MonoTypeEnum field_type = (MonoTypeEnum)0;
2494 table = &assembly->tables [MONO_TABLE_CONSTANT];
2496 alloc_table (table, table->rows);
2497 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2498 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2499 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2500 values [MONO_CONSTANT_TYPE] = field_type;
2501 values [MONO_CONSTANT_PADDING] = 0;
2506 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2508 MONO_REQ_GC_UNSAFE_MODE;
2510 MonoDynamicTable *table;
2512 guint num_methods = 0;
2516 * we need to set things in the following tables:
2517 * EVENTMAP (info already filled in _get_type_info ())
2518 * EVENT (rows already preallocated in _get_type_info ())
2519 * METHOD (method info already done with the generic method code)
2522 table = &assembly->tables [MONO_TABLE_EVENT];
2523 eb->table_idx = table->next_idx ++;
2524 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2525 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
2526 return_if_nok (error);
2527 values [MONO_EVENT_FLAGS] = eb->attrs;
2528 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2529 return_if_nok (error);
2530 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2533 * FIXME: we still don't handle 'other' methods
2535 if (eb->add_method) num_methods ++;
2536 if (eb->remove_method) num_methods ++;
2537 if (eb->raise_method) num_methods ++;
2539 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2540 table->rows += num_methods;
2541 alloc_table (table, table->rows);
2543 if (eb->add_method) {
2544 semaidx = table->next_idx ++;
2545 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2546 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2547 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2548 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2550 if (eb->remove_method) {
2551 semaidx = table->next_idx ++;
2552 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2553 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2554 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2555 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2557 if (eb->raise_method) {
2558 semaidx = table->next_idx ++;
2559 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2560 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2561 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2562 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2567 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2569 MONO_REQ_GC_UNSAFE_MODE;
2571 mono_error_init (error);
2573 MonoDynamicTable *table;
2574 guint32 num_constraints, i;
2578 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2579 num_constraints = gparam->iface_constraints ?
2580 mono_array_length (gparam->iface_constraints) : 0;
2581 table->rows += num_constraints;
2582 if (gparam->base_type)
2584 alloc_table (table, table->rows);
2586 if (gparam->base_type) {
2587 table_idx = table->next_idx ++;
2588 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2590 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2591 return_if_nok (error);
2592 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2593 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2596 for (i = 0; i < num_constraints; i++) {
2597 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2598 gparam->iface_constraints, gpointer, i);
2600 table_idx = table->next_idx ++;
2601 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2603 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2604 return_if_nok (error);
2606 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2607 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2612 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2614 MONO_REQ_GC_UNSAFE_MODE;
2616 GenericParamTableEntry *entry;
2619 * The GenericParam table must be sorted according to the `owner' field.
2620 * We need to do this sorting prior to writing the GenericParamConstraint
2621 * table, since we have to use the final GenericParam table indices there
2622 * and they must also be sorted.
2625 entry = g_new0 (GenericParamTableEntry, 1);
2626 entry->owner = owner;
2627 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2628 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2629 entry->gparam = gparam;
2631 g_ptr_array_add (assembly->gen_params, entry);
2635 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2637 MONO_REQ_GC_UNSAFE_MODE;
2639 MonoDynamicTable *table;
2640 MonoGenericParam *param;
2644 mono_error_init (error);
2646 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2647 table_idx = table->next_idx ++;
2648 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2650 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2651 return_val_if_nok (error, FALSE);
2653 param = gparam_type->data.generic_param;
2655 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2656 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2657 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2658 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2660 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2663 encode_constraints (entry->gparam, table_idx, assembly, error);
2664 return_val_if_nok (error, FALSE);
2670 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2672 MONO_REQ_GC_UNSAFE_MODE;
2674 MonoDynamicTable *table;
2677 guint32 cols [MONO_ASSEMBLY_SIZE];
2681 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2684 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2685 table = &assembly->tables [MONO_TABLE_MODULEREF];
2686 token = table->next_idx ++;
2688 alloc_table (table, table->rows);
2689 values = table->values + token * MONO_MODULEREF_SIZE;
2690 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2692 token <<= MONO_RESOLUTION_SCOPE_BITS;
2693 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2694 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2699 if (assembly_is_dynamic (image->assembly))
2701 memset (cols, 0, sizeof (cols));
2703 /* image->assembly->image is the manifest module */
2704 image = image->assembly->image;
2705 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2708 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2709 token = table->next_idx ++;
2711 alloc_table (table, table->rows);
2712 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2713 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2714 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2715 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2716 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2717 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2718 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2719 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2720 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2722 if (strcmp ("", image->assembly->aname.culture)) {
2723 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2724 image->assembly->aname.culture);
2727 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2728 guchar pubtoken [9];
2730 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2731 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2733 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2735 token <<= MONO_RESOLUTION_SCOPE_BITS;
2736 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2737 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2742 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2744 MONO_REQ_GC_NEUTRAL_MODE;
2746 MonoDynamicTable *table;
2751 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2754 sigbuffer_init (&buf, 32);
2755 switch (type->type) {
2756 case MONO_TYPE_FNPTR:
2758 case MONO_TYPE_SZARRAY:
2759 case MONO_TYPE_ARRAY:
2761 case MONO_TYPE_MVAR:
2762 case MONO_TYPE_GENERICINST:
2763 encode_type (assembly, type, &buf);
2765 case MONO_TYPE_CLASS:
2766 case MONO_TYPE_VALUETYPE: {
2767 MonoClass *k = mono_class_from_mono_type (type);
2768 if (!k || !k->generic_container) {
2769 sigbuffer_free (&buf);
2772 encode_type (assembly, type, &buf);
2776 sigbuffer_free (&buf);
2780 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2781 if (assembly->save) {
2782 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2783 alloc_table (table, table->rows + 1);
2784 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2785 values [MONO_TYPESPEC_SIGNATURE] = token;
2787 sigbuffer_free (&buf);
2789 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2790 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2796 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2798 MONO_REQ_GC_UNSAFE_MODE;
2800 MonoDynamicTable *table;
2802 guint32 token, scope, enclosing;
2805 /* if the type requires a typespec, we must try that first*/
2806 if (try_typespec && (token = create_typespec (assembly, type)))
2808 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2811 klass = mono_class_from_mono_type (type);
2813 klass = mono_class_from_mono_type (type);
2816 * If it's in the same module and not a generic type parameter:
2818 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2819 (type->type != MONO_TYPE_MVAR)) {
2820 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2821 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2822 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2826 if (klass->nested_in) {
2827 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2828 /* get the typeref idx of the enclosing type */
2829 enclosing >>= MONO_TYPEDEFORREF_BITS;
2830 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2832 scope = resolution_scope_from_image (assembly, klass->image);
2834 table = &assembly->tables [MONO_TABLE_TYPEREF];
2835 if (assembly->save) {
2836 alloc_table (table, table->rows + 1);
2837 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2838 values [MONO_TYPEREF_SCOPE] = scope;
2839 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2840 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2842 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2843 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2845 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2850 * Despite the name, we handle also TypeSpec (with the above helper).
2853 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2855 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2858 #ifndef DISABLE_REFLECTION_EMIT
2860 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2862 MONO_REQ_GC_NEUTRAL_MODE;
2864 MonoDynamicTable *table;
2866 guint32 token, pclass;
2868 switch (parent & MONO_TYPEDEFORREF_MASK) {
2869 case MONO_TYPEDEFORREF_TYPEREF:
2870 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2872 case MONO_TYPEDEFORREF_TYPESPEC:
2873 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2875 case MONO_TYPEDEFORREF_TYPEDEF:
2876 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2879 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2882 /* extract the index */
2883 parent >>= MONO_TYPEDEFORREF_BITS;
2885 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2887 if (assembly->save) {
2888 alloc_table (table, table->rows + 1);
2889 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2890 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2891 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2892 values [MONO_MEMBERREF_SIGNATURE] = sig;
2895 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2902 * Insert a memberef row into the metadata: the token that point to the memberref
2903 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2904 * mono_image_get_fieldref_token()).
2905 * The sig param is an index to an already built signature.
2908 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2910 MONO_REQ_GC_NEUTRAL_MODE;
2912 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2913 return mono_image_add_memberef_row (assembly, parent, name, sig);
2918 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2920 MONO_REQ_GC_NEUTRAL_MODE;
2923 MonoMethodSignature *sig;
2925 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2927 if (create_typespec) {
2928 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2933 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2934 if (token && !create_typespec)
2937 g_assert (!method->is_inflated);
2940 * A methodref signature can't contain an unmanaged calling convention.
2942 sig = mono_metadata_signature_dup (mono_method_signature (method));
2943 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2944 sig->call_convention = MONO_CALL_DEFAULT;
2945 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2946 method->name, method_encode_signature (assembly, sig));
2948 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2951 if (create_typespec) {
2952 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2953 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2954 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2956 if (assembly->save) {
2959 alloc_table (table, table->rows + 1);
2960 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2961 values [MONO_METHODSPEC_METHOD] = token;
2962 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2965 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2967 /*methodspec and memberef tokens are diferent, */
2968 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2975 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2977 guint32 token, parent, sig;
2978 ReflectionMethodBuilder rmb;
2979 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2981 mono_error_init (error);
2982 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2986 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2990 * A methodref signature can't contain an unmanaged calling convention.
2991 * Since some flags are encoded as part of call_conv, we need to check against it.
2993 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2994 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2996 sig = method_builder_encode_signature (assembly, &rmb, error);
2997 return_val_if_nok (error, 0);
2999 if (tb->generic_params) {
3000 parent = create_generic_typespec (assembly, tb, error);
3001 return_val_if_nok (error, 0);
3003 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
3004 return_val_if_nok (error, 0);
3006 parent = mono_image_typedef_or_ref (assembly, t);
3009 char *name = mono_string_to_utf8_checked (method->name, error);
3010 return_val_if_nok (error, 0);
3012 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3015 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3021 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3022 const gchar *name, guint32 sig)
3024 MonoDynamicTable *table;
3028 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3030 if (assembly->save) {
3031 alloc_table (table, table->rows + 1);
3032 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3033 values [MONO_MEMBERREF_CLASS] = original;
3034 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3035 values [MONO_MEMBERREF_SIGNATURE] = sig;
3038 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3045 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3049 guint32 nparams = mono_array_length (mb->generic_params);
3052 if (!assembly->save)
3055 sigbuffer_init (&buf, 32);
3057 sigbuffer_add_value (&buf, 0xa);
3058 sigbuffer_add_value (&buf, nparams);
3060 for (i = 0; i < nparams; i++) {
3061 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3062 sigbuffer_add_value (&buf, i);
3065 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3066 sigbuffer_free (&buf);
3071 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3073 MonoDynamicTable *table;
3075 guint32 token, mtoken = 0;
3077 mono_error_init (error);
3078 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3082 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3084 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3085 if (!mono_error_ok (error))
3088 switch (mono_metadata_token_table (mtoken)) {
3089 case MONO_TABLE_MEMBERREF:
3090 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3092 case MONO_TABLE_METHOD:
3093 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3096 g_assert_not_reached ();
3099 if (assembly->save) {
3100 alloc_table (table, table->rows + 1);
3101 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3102 values [MONO_METHODSPEC_METHOD] = mtoken;
3103 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3106 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3109 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3114 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3118 mono_error_init (error);
3120 if (mb->generic_params && create_methodspec)
3121 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3123 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3127 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3128 if (!mono_error_ok (error))
3130 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3135 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3137 guint32 token, parent, sig;
3138 ReflectionMethodBuilder rmb;
3140 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3142 mono_error_init (error);
3144 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3148 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3151 if (tb->generic_params) {
3152 parent = create_generic_typespec (assembly, tb, error);
3153 return_val_if_nok (error, 0);
3155 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3156 return_val_if_nok (error, 0);
3157 parent = mono_image_typedef_or_ref (assembly, type);
3160 name = mono_string_to_utf8_checked (rmb.name, error);
3161 return_val_if_nok (error, 0);
3162 sig = method_builder_encode_signature (assembly, &rmb, error);
3163 return_val_if_nok (error, 0);
3165 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3168 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3174 is_field_on_inst (MonoClassField *field)
3176 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3180 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3183 get_field_on_inst_generic_type (MonoClassField *field)
3185 MonoClass *klass, *gtd;
3186 MonoDynamicGenericClass *dgclass;
3189 g_assert (is_field_on_inst (field));
3191 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3193 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3194 field_index = field - dgclass->fields;
3195 return dgclass->field_generic_types [field_index];
3198 klass = field->parent;
3199 gtd = klass->generic_class->container_class;
3201 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3202 field_index = field - klass->fields;
3203 return gtd->fields [field_index].type;
3206 g_assert_not_reached ();
3210 #ifndef DISABLE_REFLECTION_EMIT
3212 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3218 g_assert (field->parent);
3220 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3224 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3225 int index = field - field->parent->fields;
3226 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3228 if (is_field_on_inst (field))
3229 type = get_field_on_inst_generic_type (field);
3231 type = mono_field_get_type (field);
3233 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3234 mono_field_get_name (field),
3235 fieldref_encode_signature (assembly, field->parent->image, type));
3236 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3241 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3245 MonoGenericClass *gclass;
3249 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3252 if (is_sre_field_builder (mono_object_class (f->fb))) {
3253 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3254 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3255 return_val_if_nok (error, 0);
3256 klass = mono_class_from_mono_type (type);
3257 gclass = type->data.generic_class;
3258 g_assert (gclass->is_dynamic);
3260 guint32 sig_token = field_encode_signature (assembly, fb, error);
3261 return_val_if_nok (error, 0);
3262 name = mono_string_to_utf8_checked (fb->name, error);
3263 return_val_if_nok (error, 0);
3264 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3266 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3268 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3270 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3271 return_val_if_nok (error, 0);
3272 klass = mono_class_from_mono_type (type);
3274 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3275 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3277 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3278 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3281 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3286 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3290 MonoGenericClass *gclass;
3293 mono_error_init (error);
3295 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3297 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3301 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3302 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3303 ReflectionMethodBuilder rmb;
3306 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3307 return_val_if_nok (error, 0);
3308 klass = mono_class_from_mono_type (type);
3310 gclass = type->data.generic_class;
3311 g_assert (gclass->is_dynamic);
3313 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3316 sig = method_builder_encode_signature (assembly, &rmb, error);
3317 return_val_if_nok (error, 0);
3319 name = mono_string_to_utf8_checked (rmb.name, error);
3320 return_val_if_nok (error, 0);
3322 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3324 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3325 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3327 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3328 return_val_if_nok (error, 0);
3329 klass = mono_class_from_mono_type (type);
3331 sig = method_encode_signature (assembly, mono_method_signature (mm));
3332 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3334 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3335 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3339 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3344 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3347 MonoGenericContext tmp_context;
3348 MonoType **type_argv;
3349 MonoGenericInst *ginst;
3350 MonoMethod *method, *inflated;
3353 mono_error_init (error);
3355 init_type_builder_generics ((MonoObject*)m->inst, error);
3356 return_val_if_nok (error, NULL);
3358 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3359 return_val_if_nok (error, NULL);
3361 klass = method->klass;
3363 if (m->method_args == NULL)
3366 if (method->is_inflated)
3367 method = ((MonoMethodInflated *) method)->declaring;
3369 count = mono_array_length (m->method_args);
3371 type_argv = g_new0 (MonoType *, count);
3372 for (i = 0; i < count; i++) {
3373 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3374 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3375 return_val_if_nok (error, NULL);
3377 ginst = mono_metadata_get_generic_inst (count, type_argv);
3380 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3381 tmp_context.method_inst = ginst;
3383 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3384 mono_error_assert_ok (error);
3389 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3391 guint32 sig, token = 0;
3395 mono_error_init (error);
3397 if (m->method_args) {
3398 MonoMethod *inflated;
3400 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3401 return_val_if_nok (error, 0);
3403 if (create_methodspec)
3404 token = mono_image_get_methodspec_token (assembly, inflated);
3406 token = mono_image_get_inflated_method_token (assembly, inflated);
3410 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3414 if (is_sre_method_builder (mono_object_class (m->mb))) {
3415 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3416 MonoGenericClass *gclass;
3417 ReflectionMethodBuilder rmb;
3420 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3421 return_val_if_nok (error, 0);
3422 klass = mono_class_from_mono_type (type);
3423 gclass = type->data.generic_class;
3424 g_assert (gclass->is_dynamic);
3426 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3429 sig = method_builder_encode_signature (assembly, &rmb, error);
3430 return_val_if_nok (error, 0);
3432 name = mono_string_to_utf8_checked (rmb.name, error);
3433 return_val_if_nok (error, 0);
3435 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3437 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3438 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3440 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3441 return_val_if_nok (error, 0);
3442 klass = mono_class_from_mono_type (type);
3444 sig = method_encode_signature (assembly, mono_method_signature (mm));
3445 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3447 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3448 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3451 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3456 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3460 guint32 nparams = context->method_inst->type_argc;
3463 if (!assembly->save)
3466 sigbuffer_init (&buf, 32);
3468 * FIXME: vararg, explicit_this, differenc call_conv values...
3470 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3471 sigbuffer_add_value (&buf, nparams);
3473 for (i = 0; i < nparams; i++)
3474 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3476 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3477 sigbuffer_free (&buf);
3482 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3484 MonoDynamicTable *table;
3486 guint32 token, mtoken = 0, sig;
3487 MonoMethodInflated *imethod;
3488 MonoMethod *declaring;
3490 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3492 g_assert (method->is_inflated);
3493 imethod = (MonoMethodInflated *) method;
3494 declaring = imethod->declaring;
3496 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3497 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3499 if (!mono_method_signature (declaring)->generic_param_count)
3502 switch (mono_metadata_token_table (mtoken)) {
3503 case MONO_TABLE_MEMBERREF:
3504 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3506 case MONO_TABLE_METHOD:
3507 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3510 g_assert_not_reached ();
3513 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3515 if (assembly->save) {
3516 alloc_table (table, table->rows + 1);
3517 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3518 values [MONO_METHODSPEC_METHOD] = mtoken;
3519 values [MONO_METHODSPEC_SIGNATURE] = sig;
3522 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3529 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3531 MonoMethodInflated *imethod;
3534 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3538 g_assert (method->is_inflated);
3539 imethod = (MonoMethodInflated *) method;
3541 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3542 token = method_encode_methodspec (assembly, method);
3544 guint32 sig = method_encode_signature (
3545 assembly, mono_method_signature (imethod->declaring));
3546 token = mono_image_get_memberref_token (
3547 assembly, &method->klass->byval_arg, method->name, sig);
3550 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3555 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3557 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3560 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3561 token = mono_image_get_memberref_token (
3562 assembly, &m->klass->byval_arg, m->name, sig);
3568 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3570 MonoDynamicTable *table;
3579 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3580 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3581 * Because of this, we must not insert it into the `typeref' hash table.
3583 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3584 return_val_if_nok (error, 0);
3585 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3589 sigbuffer_init (&buf, 32);
3591 g_assert (tb->generic_params);
3592 klass = mono_class_from_mono_type (type);
3594 if (tb->generic_container) {
3595 if (!mono_reflection_create_generic_class (tb, error))
3599 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3600 g_assert (klass->generic_container);
3601 sigbuffer_add_value (&buf, klass->byval_arg.type);
3602 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3604 count = mono_array_length (tb->generic_params);
3605 sigbuffer_add_value (&buf, count);
3606 for (i = 0; i < count; i++) {
3607 MonoReflectionGenericParam *gparam;
3609 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3610 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3614 encode_type (assembly, gparam_type, &buf);
3617 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3619 if (assembly->save) {
3620 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3621 alloc_table (table, table->rows + 1);
3622 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3623 values [MONO_TYPESPEC_SIGNATURE] = token;
3625 sigbuffer_free (&buf);
3627 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3628 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3632 sigbuffer_free (&buf);
3637 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3640 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3642 int i, count, len, pos;
3645 mono_error_init (error);
3649 count += mono_array_length (modreq);
3651 count += mono_array_length (modopt);
3654 return mono_metadata_type_dup (NULL, type);
3656 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3657 t = (MonoType *)g_malloc (len);
3658 memcpy (t, type, MONO_SIZEOF_TYPE);
3660 t->num_mods = count;
3663 for (i = 0; i < mono_array_length (modreq); ++i) {
3664 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3667 t->modifiers [pos].required = 1;
3668 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3673 for (i = 0; i < mono_array_length (modopt); ++i) {
3674 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3677 t->modifiers [pos].required = 0;
3678 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3690 init_type_builder_generics (MonoObject *type, MonoError *error)
3692 MonoReflectionTypeBuilder *tb;
3694 mono_error_init (error);
3696 if (!is_sre_type_builder(mono_object_class (type)))
3698 tb = (MonoReflectionTypeBuilder *)type;
3700 if (tb && tb->generic_container)
3701 mono_reflection_create_generic_class (tb, error);
3705 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3707 MonoDynamicTable *table;
3708 MonoType *custom = NULL, *type;
3710 guint32 token, pclass, parent, sig;
3713 mono_error_init (error);
3715 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3719 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3720 return_val_if_nok (error, 0);
3721 /* FIXME: is this call necessary? */
3722 mono_class_from_mono_type (typeb);
3724 /*FIXME this is one more layer of ugliness due how types are created.*/
3725 init_type_builder_generics (fb->type, error);
3726 return_val_if_nok (error, 0);
3728 /* fb->type does not include the custom modifiers */
3729 /* FIXME: We should do this in one place when a fieldbuilder is created */
3730 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3731 return_val_if_nok (error, 0);
3733 if (fb->modreq || fb->modopt) {
3734 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3735 return_val_if_nok (error, 0);
3738 sig = fieldref_encode_signature (assembly, NULL, type);
3741 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3742 return_val_if_nok (error, 0);
3743 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3745 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3746 parent >>= MONO_TYPEDEFORREF_BITS;
3748 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3750 name = mono_string_to_utf8_checked (fb->name, error);
3751 return_val_if_nok (error, 0);
3753 if (assembly->save) {
3754 alloc_table (table, table->rows + 1);
3755 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3756 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3757 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3758 values [MONO_MEMBERREF_SIGNATURE] = sig;
3761 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3763 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3769 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3775 mono_error_init (error);
3777 if (!assembly->save)
3780 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3781 g_assert (helper->type == 2);
3783 if (helper->arguments)
3784 nargs = mono_array_length (helper->arguments);
3788 sigbuffer_init (&buf, 32);
3790 /* Encode calling convention */
3791 /* Change Any to Standard */
3792 if ((helper->call_conv & 0x03) == 0x03)
3793 helper->call_conv = 0x01;
3794 /* explicit_this implies has_this */
3795 if (helper->call_conv & 0x40)
3796 helper->call_conv &= 0x20;
3798 if (helper->call_conv == 0) { /* Unmanaged */
3799 idx = helper->unmanaged_call_conv - 1;
3802 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3803 if (helper->call_conv & 0x02) /* varargs */
3807 sigbuffer_add_byte (&buf, idx);
3808 sigbuffer_add_value (&buf, nargs);
3809 encode_reflection_type (assembly, helper->return_type, &buf, error);
3812 for (i = 0; i < nargs; ++i) {
3813 MonoArray *modreqs = NULL;
3814 MonoArray *modopts = NULL;
3815 MonoReflectionType *pt;
3817 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3818 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3819 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3820 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3822 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3825 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3826 encode_reflection_type (assembly, pt, &buf, error);
3830 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3831 sigbuffer_free (&buf);
3835 sigbuffer_free (&buf);
3840 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3843 MonoDynamicTable *table;
3846 mono_error_init (error);
3848 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3849 idx = table->next_idx ++;
3851 alloc_table (table, table->rows);
3852 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3854 values [MONO_STAND_ALONE_SIGNATURE] =
3855 mono_reflection_encode_sighelper (assembly, helper, error);
3856 return_val_if_nok (error, 0);
3862 reflection_cc_to_file (int call_conv) {
3863 switch (call_conv & 0x3) {
3865 case 1: return MONO_CALL_DEFAULT;
3866 case 2: return MONO_CALL_VARARG;
3868 g_assert_not_reached ();
3872 #endif /* !DISABLE_REFLECTION_EMIT */
3876 MonoMethodSignature *sig;
3881 #ifndef DISABLE_REFLECTION_EMIT
3883 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3888 MonoMethodSignature *sig;
3889 ArrayMethod *am = NULL;
3892 mono_error_init (error);
3894 nparams = mono_array_length (m->parameters);
3895 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3897 sig->sentinelpos = -1;
3898 sig->call_convention = reflection_cc_to_file (m->call_conv);
3899 sig->param_count = nparams;
3901 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3905 sig->ret = &mono_defaults.void_class->byval_arg;
3907 mtype = mono_reflection_type_get_handle (m->parent, error);
3911 for (i = 0; i < nparams; ++i) {
3912 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3917 name = mono_string_to_utf8_checked (m->name, error);
3920 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3921 am = (ArrayMethod *)tmp->data;
3922 if (strcmp (name, am->name) == 0 &&
3923 mono_metadata_type_equal (am->parent, mtype) &&
3924 mono_metadata_signature_equal (am->sig, sig)) {
3927 m->table_idx = am->token & 0xffffff;
3931 am = g_new0 (ArrayMethod, 1);
3935 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3936 method_encode_signature (assembly, sig));
3937 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3938 m->table_idx = am->token & 0xffffff;
3949 * Insert into the metadata tables all the info about the TypeBuilder tb.
3950 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3953 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3955 MonoDynamicTable *table;
3957 int i, is_object = 0, is_system = 0;
3960 mono_error_init (error);
3962 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3963 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3964 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3965 n = mono_string_to_utf8_checked (tb->name, error);
3966 return_val_if_nok (error, FALSE);
3967 if (strcmp (n, "Object") == 0)
3969 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3971 n = mono_string_to_utf8_checked (tb->nspace, error);
3972 return_val_if_nok (error, FALSE);
3973 if (strcmp (n, "System") == 0)
3975 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3977 if (tb->parent && !(is_system && is_object) &&
3978 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3979 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3980 return_val_if_nok (error, FALSE);
3981 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3983 values [MONO_TYPEDEF_EXTENDS] = 0;
3985 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3986 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3989 * if we have explicitlayout or sequentiallayouts, output data in the
3990 * ClassLayout table.
3992 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3993 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3994 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3996 alloc_table (table, table->rows);
3997 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3998 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3999 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
4000 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
4003 /* handle interfaces */
4004 if (tb->interfaces) {
4005 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4007 table->rows += mono_array_length (tb->interfaces);
4008 alloc_table (table, table->rows);
4009 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4010 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4011 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4012 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4013 return_val_if_nok (error, FALSE);
4014 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4015 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4016 values += MONO_INTERFACEIMPL_SIZE;
4022 table = &assembly->tables [MONO_TABLE_FIELD];
4023 table->rows += tb->num_fields;
4024 alloc_table (table, table->rows);
4025 for (i = 0; i < tb->num_fields; ++i) {
4026 mono_image_get_field_info (
4027 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4028 return_val_if_nok (error, FALSE);
4032 /* handle constructors */
4034 table = &assembly->tables [MONO_TABLE_METHOD];
4035 table->rows += mono_array_length (tb->ctors);
4036 alloc_table (table, table->rows);
4037 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4038 if (!mono_image_get_ctor_info (domain,
4039 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4045 /* handle methods */
4047 table = &assembly->tables [MONO_TABLE_METHOD];
4048 table->rows += tb->num_methods;
4049 alloc_table (table, table->rows);
4050 for (i = 0; i < tb->num_methods; ++i) {
4051 if (!mono_image_get_method_info (
4052 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4057 /* Do the same with properties etc.. */
4058 if (tb->events && mono_array_length (tb->events)) {
4059 table = &assembly->tables [MONO_TABLE_EVENT];
4060 table->rows += mono_array_length (tb->events);
4061 alloc_table (table, table->rows);
4062 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4064 alloc_table (table, table->rows);
4065 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4066 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4067 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4068 for (i = 0; i < mono_array_length (tb->events); ++i) {
4069 mono_image_get_event_info (
4070 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4071 return_val_if_nok (error, FALSE);
4074 if (tb->properties && mono_array_length (tb->properties)) {
4075 table = &assembly->tables [MONO_TABLE_PROPERTY];
4076 table->rows += mono_array_length (tb->properties);
4077 alloc_table (table, table->rows);
4078 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4080 alloc_table (table, table->rows);
4081 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4082 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4083 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4084 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4085 mono_image_get_property_info (
4086 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4087 return_val_if_nok (error, FALSE);
4091 /* handle generic parameters */
4092 if (tb->generic_params) {
4093 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4094 table->rows += mono_array_length (tb->generic_params);
4095 alloc_table (table, table->rows);
4096 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4097 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4099 mono_image_get_generic_param_info (
4100 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4104 mono_image_add_decl_security (assembly,
4105 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4108 MonoDynamicTable *ntable;
4110 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4111 ntable->rows += mono_array_length (tb->subtypes);
4112 alloc_table (ntable, ntable->rows);
4113 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4115 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4116 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4118 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4119 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4120 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4121 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4122 mono_string_to_utf8 (tb->name), tb->table_idx,
4123 ntable->next_idx, ntable->rows);*/
4124 values += MONO_NESTED_CLASS_SIZE;
4134 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4138 mono_ptr_array_append (*types, type);
4140 if (!type->subtypes)
4143 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4144 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4145 collect_types (types, subtype);
4150 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4152 if ((*type1)->table_idx < (*type2)->table_idx)
4155 if ((*type1)->table_idx > (*type2)->table_idx)
4162 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4165 mono_error_init (error);
4168 for (i = 0; i < mono_array_length (pinfo); ++i) {
4169 MonoReflectionParamBuilder *pb;
4170 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4173 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4181 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4184 mono_error_init (error);
4186 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4189 for (i = 0; i < tb->num_fields; ++i) {
4190 MonoReflectionFieldBuilder* fb;
4191 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4192 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4197 for (i = 0; i < mono_array_length (tb->events); ++i) {
4198 MonoReflectionEventBuilder* eb;
4199 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4200 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4204 if (tb->properties) {
4205 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4206 MonoReflectionPropertyBuilder* pb;
4207 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4208 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4213 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4214 MonoReflectionCtorBuilder* cb;
4215 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4216 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4217 !params_add_cattrs (assembly, cb->pinfo, error))
4223 for (i = 0; i < tb->num_methods; ++i) {
4224 MonoReflectionMethodBuilder* mb;
4225 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4226 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4227 !params_add_cattrs (assembly, mb->pinfo, error))
4233 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4234 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4243 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4247 mono_error_init (error);
4249 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4252 if (moduleb->global_methods) {
4253 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4254 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4255 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4256 !params_add_cattrs (assembly, mb->pinfo, error))
4261 if (moduleb->global_fields) {
4262 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4263 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4264 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4269 if (moduleb->types) {
4270 for (i = 0; i < moduleb->num_types; ++i) {
4271 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4280 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
4282 MonoDynamicTable *table;
4286 char *b = blob_size;
4289 mono_error_init (error);
4291 table = &assembly->tables [MONO_TABLE_FILE];
4293 alloc_table (table, table->rows);
4294 values = table->values + table->next_idx * MONO_FILE_SIZE;
4295 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4296 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4297 if (image_is_dynamic (module->image)) {
4298 /* This depends on the fact that the main module is emitted last */
4299 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
4300 return_val_if_nok (error, FALSE);
4301 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4304 path = g_strdup (module->image->name);
4306 mono_sha1_get_digest_from_file (path, hash);
4309 mono_metadata_encode_value (20, b, &b);
4310 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4311 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4317 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
4319 MonoDynamicTable *table;
4322 mono_error_init (error);
4324 table = &assembly->tables [MONO_TABLE_MODULE];
4325 mb->table_idx = table->next_idx ++;
4326 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
4327 return_if_nok (error);
4328 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4331 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4332 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4333 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4334 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4338 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4339 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4341 MonoDynamicTable *table;
4345 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4346 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4349 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4351 alloc_table (table, table->rows);
4352 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4354 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4355 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4356 if (klass->nested_in)
4357 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4359 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4360 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4361 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4363 res = table->next_idx;
4367 /* Emit nested types */
4368 if (klass->ext && klass->ext->nested_classes) {
4371 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4372 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4379 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4380 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4386 mono_error_init (error);
4388 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4389 return_if_nok (error);
4391 klass = mono_class_from_mono_type (t);
4393 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4395 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4396 parent_index, assembly);
4400 * We need to do this ourselves since klass->nested_classes is not set up.
4403 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4404 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4405 return_if_nok (error);
4411 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4412 guint32 module_index, MonoDynamicImage *assembly)
4414 MonoImage *image = module->image;
4418 t = &image->tables [MONO_TABLE_TYPEDEF];
4420 for (i = 0; i < t->rows; ++i) {
4422 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4423 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4425 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4426 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4431 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4433 MonoDynamicTable *table;
4435 guint32 scope, scope_idx, impl, current_idx;
4436 gboolean forwarder = TRUE;
4437 gpointer iter = NULL;
4440 if (klass->nested_in) {
4441 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4444 scope = resolution_scope_from_image (assembly, klass->image);
4445 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4446 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4447 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4450 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4453 alloc_table (table, table->rows);
4454 current_idx = table->next_idx;
4455 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4457 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4458 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4459 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4460 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4461 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4465 while ((nested = mono_class_get_nested_types (klass, &iter)))
4466 add_exported_type (assemblyb, assembly, nested, current_idx);
4470 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4476 if (!assemblyb->type_forwarders)
4479 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4480 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4485 type = mono_reflection_type_get_handle (t, &error);
4486 mono_error_assert_ok (&error);
4489 klass = mono_class_from_mono_type (type);
4491 add_exported_type (assemblyb, assembly, klass, 0);
4495 #define align_pointer(base,p)\
4497 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4499 (p) += 4 - (__diff & 3);\
4503 compare_constants (const void *a, const void *b)
4505 const guint32 *a_values = (const guint32 *)a;
4506 const guint32 *b_values = (const guint32 *)b;
4507 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4511 compare_semantics (const void *a, const void *b)
4513 const guint32 *a_values = (const guint32 *)a;
4514 const guint32 *b_values = (const guint32 *)b;
4515 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4518 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4522 compare_custom_attrs (const void *a, const void *b)
4524 const guint32 *a_values = (const guint32 *)a;
4525 const guint32 *b_values = (const guint32 *)b;
4527 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4531 compare_field_marshal (const void *a, const void *b)
4533 const guint32 *a_values = (const guint32 *)a;
4534 const guint32 *b_values = (const guint32 *)b;
4536 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4540 compare_nested (const void *a, const void *b)
4542 const guint32 *a_values = (const guint32 *)a;
4543 const guint32 *b_values = (const guint32 *)b;
4545 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4549 compare_genericparam (const void *a, const void *b)
4552 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4553 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4555 if ((*b_entry)->owner == (*a_entry)->owner) {
4556 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4557 mono_error_assert_ok (&error);
4558 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4559 mono_error_assert_ok (&error);
4561 mono_type_get_generic_param_num (a_type) -
4562 mono_type_get_generic_param_num (b_type);
4564 return (*a_entry)->owner - (*b_entry)->owner;
4568 compare_declsecurity_attrs (const void *a, const void *b)
4570 const guint32 *a_values = (const guint32 *)a;
4571 const guint32 *b_values = (const guint32 *)b;
4573 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4577 compare_interface_impl (const void *a, const void *b)
4579 const guint32 *a_values = (const guint32 *)a;
4580 const guint32 *b_values = (const guint32 *)b;
4582 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4586 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4590 pad_heap (MonoDynamicStream *sh)
4592 if (sh->index & 3) {
4593 int sz = 4 - (sh->index & 3);
4594 memset (sh->data + sh->index, 0, sz);
4601 MonoDynamicStream *stream;
4605 * build_compressed_metadata() fills in the blob of data that represents the
4606 * raw metadata as it will be saved in the PE file. The five streams are output
4607 * and the metadata tables are comnpressed from the guint32 array representation,
4608 * to the compressed on-disk format.
4611 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4613 MonoDynamicTable *table;
4615 guint64 valid_mask = 0;
4616 guint64 sorted_mask;
4617 guint32 heapt_size = 0;
4618 guint32 meta_size = 256; /* allow for header and other stuff */
4619 guint32 table_offset;
4620 guint32 ntables = 0;
4626 struct StreamDesc stream_desc [5];
4628 mono_error_init (error);
4630 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4631 for (i = 0; i < assembly->gen_params->len; i++) {
4632 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4633 if (!write_generic_param_entry (assembly, entry, error))
4637 stream_desc [0].name = "#~";
4638 stream_desc [0].stream = &assembly->tstream;
4639 stream_desc [1].name = "#Strings";
4640 stream_desc [1].stream = &assembly->sheap;
4641 stream_desc [2].name = "#US";
4642 stream_desc [2].stream = &assembly->us;
4643 stream_desc [3].name = "#Blob";
4644 stream_desc [3].stream = &assembly->blob;
4645 stream_desc [4].name = "#GUID";
4646 stream_desc [4].stream = &assembly->guid;
4648 /* tables that are sorted */
4649 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4650 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4651 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4652 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4653 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4654 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4655 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4657 /* Compute table sizes */
4658 /* the MonoImage has already been created in mono_image_basic_init() */
4659 meta = &assembly->image;
4661 /* sizes should be multiple of 4 */
4662 pad_heap (&assembly->blob);
4663 pad_heap (&assembly->guid);
4664 pad_heap (&assembly->sheap);
4665 pad_heap (&assembly->us);
4667 /* Setup the info used by compute_sizes () */
4668 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4669 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4670 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4672 meta_size += assembly->blob.index;
4673 meta_size += assembly->guid.index;
4674 meta_size += assembly->sheap.index;
4675 meta_size += assembly->us.index;
4677 for (i=0; i < MONO_TABLE_NUM; ++i)
4678 meta->tables [i].rows = assembly->tables [i].rows;
4680 for (i = 0; i < MONO_TABLE_NUM; i++){
4681 if (meta->tables [i].rows == 0)
4683 valid_mask |= (guint64)1 << i;
4685 meta->tables [i].row_size = mono_metadata_compute_size (
4686 meta, i, &meta->tables [i].size_bitfield);
4687 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4689 heapt_size += 24; /* #~ header size */
4690 heapt_size += ntables * 4;
4691 /* make multiple of 4 */
4694 meta_size += heapt_size;
4695 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4696 p = (unsigned char*)meta->raw_metadata;
4697 /* the metadata signature */
4698 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4699 /* version numbers and 4 bytes reserved */
4700 int16val = (guint16*)p;
4701 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4702 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4704 /* version string */
4705 int32val = (guint32*)p;
4706 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4708 memcpy (p, meta->version, strlen (meta->version));
4709 p += GUINT32_FROM_LE (*int32val);
4710 align_pointer (meta->raw_metadata, p);
4711 int16val = (guint16*)p;
4712 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4713 *int16val = GUINT16_TO_LE (5); /* number of streams */
4717 * write the stream info.
4719 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4720 table_offset += 3; table_offset &= ~3;
4722 assembly->tstream.index = heapt_size;
4723 for (i = 0; i < 5; ++i) {
4724 int32val = (guint32*)p;
4725 stream_desc [i].stream->offset = table_offset;
4726 *int32val++ = GUINT32_TO_LE (table_offset);
4727 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4728 table_offset += GUINT32_FROM_LE (*int32val);
4729 table_offset += 3; table_offset &= ~3;
4731 strcpy ((char*)p, stream_desc [i].name);
4732 p += strlen (stream_desc [i].name) + 1;
4733 align_pointer (meta->raw_metadata, p);
4736 * now copy the data, the table stream header and contents goes first.
4738 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4739 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4740 int32val = (guint32*)p;
4741 *int32val = GUINT32_TO_LE (0); /* reserved */
4744 *p++ = 2; /* version */
4747 if (meta->idx_string_wide)
4749 if (meta->idx_guid_wide)
4751 if (meta->idx_blob_wide)
4754 *p++ = 1; /* reserved */
4755 int64val = (guint64*)p;
4756 *int64val++ = GUINT64_TO_LE (valid_mask);
4757 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4759 int32val = (guint32*)p;
4760 for (i = 0; i < MONO_TABLE_NUM; i++){
4761 if (meta->tables [i].rows == 0)
4763 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4765 p = (unsigned char*)int32val;
4767 /* sort the tables that still need sorting */
4768 table = &assembly->tables [MONO_TABLE_CONSTANT];
4770 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4771 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4773 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4774 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4776 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4777 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4779 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4780 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4782 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4783 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4784 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4786 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4787 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4789 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4791 /* compress the tables */
4792 for (i = 0; i < MONO_TABLE_NUM; i++){
4795 guint32 bitfield = meta->tables [i].size_bitfield;
4796 if (!meta->tables [i].rows)
4798 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4799 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4800 meta->tables [i].base = (char*)p;
4801 for (row = 1; row <= meta->tables [i].rows; ++row) {
4802 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4803 for (col = 0; col < assembly->tables [i].columns; ++col) {
4804 switch (mono_metadata_table_size (bitfield, col)) {
4806 *p++ = values [col];
4809 *p++ = values [col] & 0xff;
4810 *p++ = (values [col] >> 8) & 0xff;
4813 *p++ = values [col] & 0xff;
4814 *p++ = (values [col] >> 8) & 0xff;
4815 *p++ = (values [col] >> 16) & 0xff;
4816 *p++ = (values [col] >> 24) & 0xff;
4819 g_assert_not_reached ();
4823 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4826 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4827 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4828 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4829 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4830 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4832 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4838 * Some tables in metadata need to be sorted according to some criteria, but
4839 * when methods and fields are first created with reflection, they may be assigned a token
4840 * that doesn't correspond to the final token they will get assigned after the sorting.
4841 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4842 * with the reflection objects that represent them. Once all the tables are set up, the
4843 * reflection objects will contains the correct table index. fixup_method() will fixup the
4844 * tokens for the method with ILGenerator @ilgen.
4847 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4849 guint32 code_idx = GPOINTER_TO_UINT (value);
4850 MonoReflectionILTokenInfo *iltoken;
4851 MonoReflectionFieldBuilder *field;
4852 MonoReflectionCtorBuilder *ctor;
4853 MonoReflectionMethodBuilder *method;
4854 MonoReflectionTypeBuilder *tb;
4855 MonoReflectionArrayMethod *am;
4857 unsigned char *target;
4859 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4860 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4861 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4862 switch (target [3]) {
4863 case MONO_TABLE_FIELD:
4864 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4865 field = (MonoReflectionFieldBuilder *)iltoken->member;
4866 idx = field->table_idx;
4867 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4868 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4869 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4871 g_assert_not_reached ();
4874 case MONO_TABLE_METHOD:
4875 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4876 method = (MonoReflectionMethodBuilder *)iltoken->member;
4877 idx = method->table_idx;
4878 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4879 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4880 idx = ctor->table_idx;
4881 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4882 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4883 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4884 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4886 g_assert_not_reached ();
4889 case MONO_TABLE_TYPEDEF:
4890 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4891 g_assert_not_reached ();
4892 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4893 idx = tb->table_idx;
4895 case MONO_TABLE_MEMBERREF:
4896 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4897 am = (MonoReflectionArrayMethod*)iltoken->member;
4898 idx = am->table_idx;
4899 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4900 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4901 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4902 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4903 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4904 g_assert (m->klass->generic_class || m->klass->generic_container);
4906 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4908 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4909 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4910 g_assert (is_field_on_inst (f));
4912 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4913 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4915 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4917 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4919 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4922 g_assert_not_reached ();
4925 case MONO_TABLE_METHODSPEC:
4926 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4927 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4928 g_assert (mono_method_signature (m)->generic_param_count);
4930 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4932 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4935 g_assert_not_reached ();
4939 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4941 target [0] = idx & 0xff;
4942 target [1] = (idx >> 8) & 0xff;
4943 target [2] = (idx >> 16) & 0xff;
4950 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4951 * value is not known when the table is emitted.
4954 fixup_cattrs (MonoDynamicImage *assembly)
4956 MonoDynamicTable *table;
4958 guint32 type, i, idx, token;
4961 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4963 for (i = 0; i < table->rows; ++i) {
4964 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4966 type = values [MONO_CUSTOM_ATTR_TYPE];
4967 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4968 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4969 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4970 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4973 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4974 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4975 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4976 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4977 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4978 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4979 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4980 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4987 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
4989 MonoDynamicTable *table;
4992 mono_error_init (error);
4994 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4996 alloc_table (table, table->rows);
4997 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4998 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4999 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
5000 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
5001 return_val_if_nok (error, FALSE);
5002 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
5008 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
5010 MonoDynamicTable *table;
5014 char *b = blob_size;
5016 guint32 idx, offset;
5018 mono_error_init (error);
5020 if (rsrc->filename) {
5021 name = mono_string_to_utf8_checked (rsrc->filename, error);
5022 return_val_if_nok (error, FALSE);
5023 sname = g_path_get_basename (name);
5025 table = &assembly->tables [MONO_TABLE_FILE];
5027 alloc_table (table, table->rows);
5028 values = table->values + table->next_idx * MONO_FILE_SIZE;
5029 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5030 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5033 mono_sha1_get_digest_from_file (name, hash);
5034 mono_metadata_encode_value (20, b, &b);
5035 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5036 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5038 idx = table->next_idx++;
5040 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5046 data = mono_array_addr (rsrc->data, char, 0);
5047 len = mono_array_length (rsrc->data);
5053 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5054 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5055 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5056 mono_image_add_stream_data (&assembly->resources, data, len);
5060 * The entry should be emitted into the MANIFESTRESOURCE table of
5061 * the main module, but that needs to reference the FILE table
5062 * which isn't emitted yet.
5069 return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
5073 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
5075 gchar *ver, *p, *str;
5078 mono_error_init (error);
5080 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5081 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5082 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5083 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5086 ver = str = mono_string_to_utf8_checked (version, error);
5087 return_val_if_nok (error, FALSE);
5088 for (i = 0; i < 4; ++i) {
5089 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5095 /* handle Revision and Build */
5106 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5110 char *b = blob_size;
5115 len = mono_array_length (pkey);
5116 mono_metadata_encode_value (len, b, &b);
5117 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5118 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5120 assembly->public_key = (guint8 *)g_malloc (len);
5121 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5122 assembly->public_key_len = len;
5124 /* Special case: check for ECMA key (16 bytes) */
5125 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5126 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5127 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5128 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5129 /* minimum key size (in 2.0) is 384 bits */
5130 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5132 /* FIXME - verifier */
5133 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5134 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5136 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5142 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5144 MonoDynamicTable *table;
5145 MonoDynamicImage *assembly;
5146 MonoReflectionAssemblyBuilder *assemblyb;
5150 guint32 module_index;
5152 mono_error_init (error);
5154 assemblyb = moduleb->assemblyb;
5155 assembly = moduleb->dynamic_image;
5156 domain = mono_object_domain (assemblyb);
5158 /* Emit ASSEMBLY table */
5159 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5160 alloc_table (table, 1);
5161 values = table->values + MONO_ASSEMBLY_SIZE;
5162 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5163 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
5164 return_val_if_nok (error, FALSE);
5165 if (assemblyb->culture) {
5166 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
5167 return_val_if_nok (error, FALSE);
5169 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5171 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5172 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5173 if (!set_version_from_string (assemblyb->version, values, error))
5176 /* Emit FILE + EXPORTED_TYPE table */
5178 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5180 MonoReflectionModuleBuilder *file_module =
5181 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5182 if (file_module != moduleb) {
5183 if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
5186 if (file_module->types) {
5187 for (j = 0; j < file_module->num_types; ++j) {
5188 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5189 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5190 return_val_if_nok (error, FALSE);
5195 if (assemblyb->loaded_modules) {
5196 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5197 MonoReflectionModule *file_module =
5198 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5199 if (!mono_image_fill_file_table (domain, file_module, assembly, error))
5202 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5205 if (assemblyb->type_forwarders)
5206 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5208 /* Emit MANIFESTRESOURCE table */
5210 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5212 MonoReflectionModuleBuilder *file_module =
5213 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5214 /* The table for the main module is emitted later */
5215 if (file_module != moduleb) {
5217 if (file_module->resources) {
5218 int len = mono_array_length (file_module->resources);
5219 for (j = 0; j < len; ++j) {
5220 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5221 if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
5230 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5233 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5234 * for the modulebuilder @moduleb.
5235 * At the end of the process, method and field tokens are fixed up and the
5236 * on-disk compressed metadata representation is created.
5237 * Return TRUE on success, or FALSE on failure and sets @error
5240 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5242 MonoDynamicTable *table;
5243 MonoDynamicImage *assembly;
5244 MonoReflectionAssemblyBuilder *assemblyb;
5250 mono_error_init (error);
5252 assemblyb = moduleb->assemblyb;
5253 assembly = moduleb->dynamic_image;
5254 domain = mono_object_domain (assemblyb);
5256 if (assembly->text_rva)
5259 assembly->text_rva = START_TEXT_RVA;
5261 if (moduleb->is_main) {
5262 mono_image_emit_manifest (moduleb, error);
5263 return_val_if_nok (error, FALSE);
5266 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5267 table->rows = 1; /* .<Module> */
5269 alloc_table (table, table->rows);
5271 * Set the first entry.
5273 values = table->values + table->columns;
5274 values [MONO_TYPEDEF_FLAGS] = 0;
5275 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5276 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5277 values [MONO_TYPEDEF_EXTENDS] = 0;
5278 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5279 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5282 * handle global methods
5283 * FIXME: test what to do when global methods are defined in multiple modules.
5285 if (moduleb->global_methods) {
5286 table = &assembly->tables [MONO_TABLE_METHOD];
5287 table->rows += mono_array_length (moduleb->global_methods);
5288 alloc_table (table, table->rows);
5289 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5290 if (!mono_image_get_method_info (
5291 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5295 if (moduleb->global_fields) {
5296 table = &assembly->tables [MONO_TABLE_FIELD];
5297 table->rows += mono_array_length (moduleb->global_fields);
5298 alloc_table (table, table->rows);
5299 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5300 mono_image_get_field_info (
5301 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5308 table = &assembly->tables [MONO_TABLE_MODULE];
5309 alloc_table (table, 1);
5310 mono_image_fill_module_table (domain, moduleb, assembly, error);
5314 /* Collect all types into a list sorted by their table_idx */
5315 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5318 for (i = 0; i < moduleb->num_types; ++i) {
5319 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5320 collect_types (&types, type);
5323 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5324 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5325 table->rows += mono_ptr_array_size (types);
5326 alloc_table (table, table->rows);
5329 * Emit type names + namespaces at one place inside the string heap,
5330 * so load_class_names () needs to touch fewer pages.
5332 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5333 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5334 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
5338 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5339 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5340 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
5345 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5346 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5347 if (!mono_image_get_type_info (domain, type, assembly, error))
5352 * table->rows is already set above and in mono_image_fill_module_table.
5354 /* add all the custom attributes at the end, once all the indexes are stable */
5355 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5358 /* CAS assembly permissions */
5359 if (assemblyb->permissions_minimum)
5360 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5361 if (assemblyb->permissions_optional)
5362 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5363 if (assemblyb->permissions_refused)
5364 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5366 if (!module_add_cattrs (assembly, moduleb, error))
5370 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5372 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5373 * the final tokens and don't need another fixup pass. */
5375 if (moduleb->global_methods) {
5376 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5377 MonoReflectionMethodBuilder *mb = mono_array_get (
5378 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5379 if (!mono_image_add_methodimpl (assembly, mb, error))
5384 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5385 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5386 if (type->methods) {
5387 for (j = 0; j < type->num_methods; ++j) {
5388 MonoReflectionMethodBuilder *mb = mono_array_get (
5389 type->methods, MonoReflectionMethodBuilder*, j);
5391 if (!mono_image_add_methodimpl (assembly, mb, error))
5397 fixup_cattrs (assembly);
5400 mono_ptr_array_destroy (types);
5403 return mono_error_ok (error);
5406 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5409 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5411 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5414 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5418 guint32 import_lookup_table;
5422 guint32 import_address_table_rva;
5430 #ifndef DISABLE_REFLECTION_EMIT
5433 * mono_image_insert_string:
5434 * @module: module builder object
5437 * Insert @str into the user string stream of @module.
5440 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5442 MonoDynamicImage *assembly;
5447 if (!module->dynamic_image)
5448 mono_image_module_basic_init (module);
5450 assembly = module->dynamic_image;
5452 if (assembly->save) {
5453 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5454 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5455 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5457 char *swapped = g_malloc (2 * mono_string_length (str));
5458 const char *p = (const char*)mono_string_chars (str);
5460 swap_with_size (swapped, p, 2, mono_string_length (str));
5461 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5465 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5467 mono_image_add_stream_data (&assembly->us, "", 1);
5469 idx = assembly->us.index ++;
5472 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5474 return MONO_TOKEN_STRING | idx;
5478 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5482 MonoMethodSignature *sig;
5484 mono_error_init (error);
5486 klass = obj->vtable->klass;
5487 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5488 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5489 MonoMethodSignature *old;
5490 guint32 sig_token, parent;
5493 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5495 nargs = mono_array_length (opt_param_types);
5496 old = mono_method_signature (method);
5497 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5499 sig->hasthis = old->hasthis;
5500 sig->explicit_this = old->explicit_this;
5501 sig->call_convention = old->call_convention;
5502 sig->generic_param_count = old->generic_param_count;
5503 sig->param_count = old->param_count + nargs;
5504 sig->sentinelpos = old->param_count;
5505 sig->ret = old->ret;
5507 for (i = 0; i < old->param_count; i++)
5508 sig->params [i] = old->params [i];
5510 for (i = 0; i < nargs; i++) {
5511 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5512 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5513 if (!is_ok (error)) goto fail;
5516 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5517 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5518 parent >>= MONO_TYPEDEFORREF_BITS;
5520 parent <<= MONO_MEMBERREF_PARENT_BITS;
5521 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5523 sig_token = method_encode_signature (assembly, sig);
5524 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5525 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5526 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5527 ReflectionMethodBuilder rmb;
5528 guint32 parent, sig_token;
5529 int nopt_args, nparams, ngparams, i;
5531 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5534 rmb.opt_types = opt_param_types;
5535 nopt_args = mono_array_length (opt_param_types);
5537 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5538 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5539 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5541 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5542 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5543 sig->call_convention = rmb.call_conv;
5544 sig->generic_param_count = ngparams;
5545 sig->param_count = nparams + nopt_args;
5546 sig->sentinelpos = nparams;
5547 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5548 if (!is_ok (error)) goto fail;
5550 for (i = 0; i < nparams; i++) {
5551 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5552 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5553 if (!is_ok (error)) goto fail;
5556 for (i = 0; i < nopt_args; i++) {
5557 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5558 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5559 if (!is_ok (error)) goto fail;
5562 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5566 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5567 if (!mono_error_ok (error))
5569 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5571 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5572 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5574 char *name = mono_string_to_utf8_checked (rmb.name, error);
5575 if (!is_ok (error)) goto fail;
5576 token = mono_image_get_varargs_method_token (
5577 assembly, parent, name, sig_token);
5580 g_error ("requested method token for %s\n", klass->name);
5583 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5584 register_dyn_token (assembly, token, obj);
5587 g_assert (!mono_error_ok (error));
5592 * mono_image_create_token:
5593 * @assembly: a dynamic assembly
5595 * @register_token: Whenever to register the token in the assembly->tokens hash.
5597 * Get a token to insert in the IL code stream for the given MemberInfo.
5598 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5599 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5603 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5604 gboolean create_open_instance, gboolean register_token,
5610 mono_error_init (error);
5612 klass = obj->vtable->klass;
5614 /* Check for user defined reflection objects */
5615 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5616 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5617 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5621 if (strcmp (klass->name, "MethodBuilder") == 0) {
5622 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5623 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5625 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5626 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5628 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5629 if (!mono_error_ok (error))
5632 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5633 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5634 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5635 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5637 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5638 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5640 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5641 if (!mono_error_ok (error))
5644 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5645 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5646 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5647 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5648 if (tb->generic_params) {
5649 token = mono_image_get_generic_field_token (assembly, fb, error);
5650 return_val_if_nok (error, 0);
5652 if (tb->module->dynamic_image == assembly) {
5653 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5655 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5658 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5659 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5660 if (create_open_instance && tb->generic_params) {
5662 init_type_builder_generics (obj, error);
5663 return_val_if_nok (error, 0);
5664 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5665 return_val_if_nok (error, 0);
5666 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5667 token = mono_metadata_token_from_dor (token);
5668 } else if (tb->module->dynamic_image == assembly) {
5669 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5672 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5673 return_val_if_nok (error, 0);
5674 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5676 } else if (strcmp (klass->name, "RuntimeType") == 0) {
5677 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5678 return_val_if_nok (error, 0);
5679 MonoClass *mc = mono_class_from_mono_type (type);
5680 token = mono_metadata_token_from_dor (
5681 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5682 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5683 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5684 return_val_if_nok (error, 0);
5685 token = mono_metadata_token_from_dor (
5686 mono_image_typedef_or_ref (assembly, type));
5687 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5688 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5689 return_val_if_nok (error, 0);
5690 token = mono_metadata_token_from_dor (
5691 mono_image_typedef_or_ref (assembly, type));
5692 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5693 strcmp (klass->name, "MonoMethod") == 0 ||
5694 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5695 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5696 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5697 if (m->method->is_inflated) {
5698 if (create_open_instance)
5699 token = mono_image_get_methodspec_token (assembly, m->method);
5701 token = mono_image_get_inflated_method_token (assembly, m->method);
5702 } else if ((m->method->klass->image == &assembly->image) &&
5703 !m->method->klass->generic_class) {
5704 static guint32 method_table_idx = 0xffffff;
5705 if (m->method->klass->wastypebuilder) {
5706 /* we use the same token as the one that was assigned
5707 * to the Methodbuilder.
5708 * FIXME: do the equivalent for Fields.
5710 token = m->method->token;
5713 * Each token should have a unique index, but the indexes are
5714 * assigned by managed code, so we don't know about them. An
5715 * easy solution is to count backwards...
5717 method_table_idx --;
5718 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5721 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5723 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5724 } else if (strcmp (klass->name, "MonoField") == 0) {
5725 MonoReflectionField *f = (MonoReflectionField *)obj;
5726 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5727 static guint32 field_table_idx = 0xffffff;
5729 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5731 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5733 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5734 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5735 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5736 token = mono_image_get_array_token (assembly, m, error);
5737 return_val_if_nok (error, 0);
5738 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5739 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5740 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5741 return_val_if_nok (error, 0);
5742 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5743 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5744 return_val_if_nok (error, 0);
5745 token = mono_metadata_token_from_dor (
5746 mono_image_typedef_or_ref (assembly, type));
5747 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5748 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5749 token = mono_image_get_field_on_inst_token (assembly, f, error);
5750 return_val_if_nok (error, 0);
5751 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5752 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5753 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5754 if (!mono_error_ok (error))
5756 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5757 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5758 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5759 if (!mono_error_ok (error))
5761 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5762 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5763 return_val_if_nok (error, 0);
5764 token = mono_metadata_token_from_dor (
5765 mono_image_typedef_or_ref (assembly, type));
5767 g_error ("requested token for %s\n", klass->name);
5771 mono_image_register_token (assembly, token, obj);
5777 * mono_image_register_token:
5779 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5780 * the Module.ResolveXXXToken () methods to work.
5783 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5787 dynamic_image_lock (assembly);
5788 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5790 /* There could be multiple MethodInfo objects with the same token */
5791 //g_assert (prev == obj);
5793 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5795 dynamic_image_unlock (assembly);
5798 static MonoDynamicImage*
5799 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5801 static const guchar entrycode [16] = {0xff, 0x25, 0};
5802 MonoDynamicImage *image;
5805 const char *version;
5807 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5808 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5810 version = mono_get_runtime_info ()->runtime_version;
5813 /* The MonoGHashTable's need GC tracking */
5814 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5816 image = g_new0 (MonoDynamicImage, 1);
5819 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5821 /*g_print ("created image %p\n", image);*/
5822 /* keep in sync with image.c */
5823 image->image.name = assembly_name;
5824 image->image.assembly_name = image->image.name; /* they may be different */
5825 image->image.module_name = module_name;
5826 image->image.version = g_strdup (version);
5827 image->image.md_version_major = 1;
5828 image->image.md_version_minor = 1;
5829 image->image.dynamic = TRUE;
5831 image->image.references = g_new0 (MonoAssembly*, 1);
5832 image->image.references [0] = NULL;
5834 mono_image_init (&image->image);
5836 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");
5837 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5838 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5839 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5840 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5841 image->handleref = g_hash_table_new (NULL, NULL);
5842 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");
5843 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5844 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");
5845 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");
5846 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5847 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5848 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5849 image->gen_params = g_ptr_array_new ();
5850 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5852 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5853 string_heap_init (&image->sheap);
5854 mono_image_add_stream_data (&image->us, "", 1);
5855 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5856 /* import tables... */
5857 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5858 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5859 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5860 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5861 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5862 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5863 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5864 stream_data_align (&image->code);
5866 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5868 for (i=0; i < MONO_TABLE_NUM; ++i) {
5869 image->tables [i].next_idx = 1;
5870 image->tables [i].columns = table_sizes [i];
5873 image->image.assembly = (MonoAssembly*)assembly;
5874 image->run = assembly->run;
5875 image->save = assembly->save;
5876 image->pe_kind = 0x1; /* ILOnly */
5877 image->machine = 0x14c; /* I386 */
5879 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5881 dynamic_images_lock ();
5883 if (!dynamic_images)
5884 dynamic_images = g_ptr_array_new ();
5886 g_ptr_array_add (dynamic_images, image);
5888 dynamic_images_unlock ();
5895 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5901 release_hashtable (MonoGHashTable **hash)
5904 mono_g_hash_table_destroy (*hash);
5910 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5912 release_hashtable (&image->token_fixups);
5913 release_hashtable (&image->handleref_managed);
5914 release_hashtable (&image->tokens);
5915 release_hashtable (&image->remapped_tokens);
5916 release_hashtable (&image->generic_def_objects);
5917 release_hashtable (&image->methodspec);
5920 // Free dynamic image pass one: Free resources but not image itself
5922 mono_dynamic_image_free (MonoDynamicImage *image)
5924 MonoDynamicImage *di = image;
5929 mono_g_hash_table_destroy (di->methodspec);
5931 g_hash_table_destroy (di->typespec);
5933 g_hash_table_destroy (di->typeref);
5935 g_hash_table_destroy (di->handleref);
5936 if (di->handleref_managed)
5937 mono_g_hash_table_destroy (di->handleref_managed);
5939 mono_g_hash_table_destroy (di->tokens);
5940 if (di->remapped_tokens)
5941 mono_g_hash_table_destroy (di->remapped_tokens);
5942 if (di->generic_def_objects)
5943 mono_g_hash_table_destroy (di->generic_def_objects);
5944 if (di->blob_cache) {
5945 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5946 g_hash_table_destroy (di->blob_cache);
5948 if (di->standalonesig_cache)
5949 g_hash_table_destroy (di->standalonesig_cache);
5950 for (list = di->array_methods; list; list = list->next) {
5951 ArrayMethod *am = (ArrayMethod *)list->data;
5956 g_list_free (di->array_methods);
5957 if (di->gen_params) {
5958 for (i = 0; i < di->gen_params->len; i++) {
5959 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5960 mono_gc_deregister_root ((char*) &entry->gparam);
5963 g_ptr_array_free (di->gen_params, TRUE);
5965 if (di->token_fixups)
5966 mono_g_hash_table_destroy (di->token_fixups);
5967 if (di->method_to_table_idx)
5968 g_hash_table_destroy (di->method_to_table_idx);
5969 if (di->field_to_table_idx)
5970 g_hash_table_destroy (di->field_to_table_idx);
5971 if (di->method_aux_hash)
5972 g_hash_table_destroy (di->method_aux_hash);
5973 if (di->vararg_aux_hash)
5974 g_hash_table_destroy (di->vararg_aux_hash);
5975 g_free (di->strong_name);
5976 g_free (di->win32_res);
5978 g_free (di->public_key);
5980 /*g_print ("string heap destroy for image %p\n", di);*/
5981 mono_dynamic_stream_reset (&di->sheap);
5982 mono_dynamic_stream_reset (&di->code);
5983 mono_dynamic_stream_reset (&di->resources);
5984 mono_dynamic_stream_reset (&di->us);
5985 mono_dynamic_stream_reset (&di->blob);
5986 mono_dynamic_stream_reset (&di->tstream);
5987 mono_dynamic_stream_reset (&di->guid);
5988 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5989 g_free (di->tables [i].values);
5992 dynamic_images_lock ();
5995 g_ptr_array_remove (dynamic_images, di);
5997 dynamic_images_unlock ();
6000 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
6002 mono_dynamic_image_free_image (MonoDynamicImage *image)
6004 /* See create_dynamic_mono_image () */
6006 /* Allocated using GC_MALLOC */
6012 #ifndef DISABLE_REFLECTION_EMIT
6015 * mono_image_basic_init:
6016 * @assembly: an assembly builder object
6018 * Create the MonoImage that represents the assembly builder and setup some
6019 * of the helper hash table and the basic metadata streams.
6022 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
6025 MonoDynamicAssembly *assembly;
6026 MonoDynamicImage *image;
6027 MonoDomain *domain = mono_object_domain (assemblyb);
6029 if (assemblyb->dynamic_assembly)
6033 /* assembly->assembly.image might be GC allocated */
6034 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6036 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6039 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6041 assembly->assembly.ref_count = 1;
6042 assembly->assembly.dynamic = TRUE;
6043 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6044 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6045 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6046 if (mono_error_set_pending_exception (&error))
6048 if (assemblyb->culture) {
6049 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6050 if (mono_error_set_pending_exception (&error))
6053 assembly->assembly.aname.culture = g_strdup ("");
6055 if (assemblyb->version) {
6056 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6057 if (mono_error_set_pending_exception (&error))
6059 char **version = g_strsplit (vstr, ".", 4);
6060 char **parts = version;
6061 assembly->assembly.aname.major = atoi (*parts++);
6062 assembly->assembly.aname.minor = atoi (*parts++);
6063 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6064 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6066 g_strfreev (version);
6069 assembly->assembly.aname.major = 0;
6070 assembly->assembly.aname.minor = 0;
6071 assembly->assembly.aname.build = 0;
6072 assembly->assembly.aname.revision = 0;
6075 assembly->run = assemblyb->access != 2;
6076 assembly->save = assemblyb->access != 1;
6077 assembly->domain = domain;
6079 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6080 if (mono_error_set_pending_exception (&error))
6082 image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6083 image->initial_image = TRUE;
6084 assembly->assembly.aname.name = image->image.name;
6085 assembly->assembly.image = &image->image;
6086 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6087 /* -1 to correct for the trailing NULL byte */
6088 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6089 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6091 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6094 mono_domain_assemblies_lock (domain);
6095 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6096 mono_domain_assemblies_unlock (domain);
6098 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6100 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6102 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6105 #endif /* !DISABLE_REFLECTION_EMIT */
6107 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6110 calc_section_size (MonoDynamicImage *assembly)
6114 /* alignment constraints */
6115 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6116 g_assert ((assembly->code.index % 4) == 0);
6117 assembly->meta_size += 3;
6118 assembly->meta_size &= ~3;
6119 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6120 g_assert ((assembly->resources.index % 4) == 0);
6122 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6123 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6126 if (assembly->win32_res) {
6127 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6129 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6130 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6134 assembly->sections [MONO_SECTION_RELOC].size = 12;
6135 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6145 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6149 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6151 ResTreeNode *t1 = (ResTreeNode*)a;
6152 ResTreeNode *t2 = (ResTreeNode*)b;
6154 return t1->id - t2->id;
6158 * resource_tree_create:
6160 * Organize the resources into a resource tree.
6162 static ResTreeNode *
6163 resource_tree_create (MonoArray *win32_resources)
6165 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6169 tree = g_new0 (ResTreeNode, 1);
6171 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6172 MonoReflectionWin32Resource *win32_res =
6173 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6177 /* FIXME: BUG: this stores managed references in unmanaged memory */
6178 lang_node = g_new0 (ResTreeNode, 1);
6179 lang_node->id = win32_res->lang_id;
6180 lang_node->win32_res = win32_res;
6182 /* Create type node if neccesary */
6184 for (l = tree->children; l; l = l->next)
6185 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6186 type_node = (ResTreeNode*)l->data;
6191 type_node = g_new0 (ResTreeNode, 1);
6192 type_node->id = win32_res->res_type;
6195 * The resource types have to be sorted otherwise
6196 * Windows Explorer can't display the version information.
6198 tree->children = g_slist_insert_sorted (tree->children,
6199 type_node, resource_tree_compare_by_id);
6202 /* Create res node if neccesary */
6204 for (l = type_node->children; l; l = l->next)
6205 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6206 res_node = (ResTreeNode*)l->data;
6211 res_node = g_new0 (ResTreeNode, 1);
6212 res_node->id = win32_res->res_id;
6213 type_node->children = g_slist_append (type_node->children, res_node);
6216 res_node->children = g_slist_append (res_node->children, lang_node);
6223 * resource_tree_encode:
6225 * Encode the resource tree into the format used in the PE file.
6228 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6231 MonoPEResourceDir dir;
6232 MonoPEResourceDirEntry dir_entry;
6233 MonoPEResourceDataEntry data_entry;
6235 guint32 res_id_entries;
6238 * For the format of the resource directory, see the article
6239 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6243 memset (&dir, 0, sizeof (dir));
6244 memset (&dir_entry, 0, sizeof (dir_entry));
6245 memset (&data_entry, 0, sizeof (data_entry));
6247 g_assert (sizeof (dir) == 16);
6248 g_assert (sizeof (dir_entry) == 8);
6249 g_assert (sizeof (data_entry) == 16);
6251 node->offset = p - begin;
6253 /* IMAGE_RESOURCE_DIRECTORY */
6254 res_id_entries = g_slist_length (node->children);
6255 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6257 memcpy (p, &dir, sizeof (dir));
6260 /* Reserve space for entries */
6262 p += sizeof (dir_entry) * res_id_entries;
6264 /* Write children */
6265 for (l = node->children; l; l = l->next) {
6266 ResTreeNode *child = (ResTreeNode*)l->data;
6268 if (child->win32_res) {
6271 child->offset = p - begin;
6273 /* IMAGE_RESOURCE_DATA_ENTRY */
6274 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6275 size = mono_array_length (child->win32_res->res_data);
6276 data_entry.rde_size = GUINT32_TO_LE (size);
6278 memcpy (p, &data_entry, sizeof (data_entry));
6279 p += sizeof (data_entry);
6281 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6284 resource_tree_encode (child, begin, p, &p);
6288 /* IMAGE_RESOURCE_ENTRY */
6289 for (l = node->children; l; l = l->next) {
6290 ResTreeNode *child = (ResTreeNode*)l->data;
6292 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6293 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6295 memcpy (entries, &dir_entry, sizeof (dir_entry));
6296 entries += sizeof (dir_entry);
6303 resource_tree_free (ResTreeNode * node)
6306 for (list = node->children; list; list = list->next)
6307 resource_tree_free ((ResTreeNode*)list->data);
6308 g_slist_free(node->children);
6313 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6318 MonoReflectionWin32Resource *win32_res;
6321 if (!assemblyb->win32_resources)
6325 * Resources are stored in a three level tree inside the PE file.
6326 * - level one contains a node for each type of resource
6327 * - level two contains a node for each resource
6328 * - level three contains a node for each instance of a resource for a
6329 * specific language.
6332 tree = resource_tree_create (assemblyb->win32_resources);
6334 /* Estimate the size of the encoded tree */
6336 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6337 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6338 size += mono_array_length (win32_res->res_data);
6340 /* Directory structure */
6341 size += mono_array_length (assemblyb->win32_resources) * 256;
6342 p = buf = (char *)g_malloc (size);
6344 resource_tree_encode (tree, p, p, &p);
6346 g_assert (p - buf <= size);
6348 assembly->win32_res = (char *)g_malloc (p - buf);
6349 assembly->win32_res_size = p - buf;
6350 memcpy (assembly->win32_res, buf, p - buf);
6353 resource_tree_free (tree);
6357 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6359 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6362 p += sizeof (MonoPEResourceDir);
6363 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6364 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6365 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6366 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6367 fixup_resource_directory (res_section, child, rva);
6369 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6370 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6373 p += sizeof (MonoPEResourceDirEntry);
6378 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6381 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6382 g_error ("WriteFile returned %d\n", GetLastError ());
6386 * mono_image_create_pefile:
6387 * @mb: a module builder object
6389 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6390 * assembly->pefile where it can be easily retrieved later in chunks.
6393 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6395 MonoMSDOSHeader *msdos;
6396 MonoDotNetHeader *header;
6397 MonoSectionTable *section;
6398 MonoCLIHeader *cli_header;
6399 guint32 size, image_size, virtual_base, text_offset;
6400 guint32 header_start, section_start, file_offset, virtual_offset;
6401 MonoDynamicImage *assembly;
6402 MonoReflectionAssemblyBuilder *assemblyb;
6403 MonoDynamicStream pefile_stream = {0};
6404 MonoDynamicStream *pefile = &pefile_stream;
6406 guint32 *rva, value;
6408 static const unsigned char msheader[] = {
6409 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6410 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6413 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6414 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6415 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6416 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6419 mono_error_init (error);
6421 assemblyb = mb->assemblyb;
6423 mono_image_basic_init (assemblyb);
6424 assembly = mb->dynamic_image;
6426 assembly->pe_kind = assemblyb->pe_kind;
6427 assembly->machine = assemblyb->machine;
6428 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6429 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6431 if (!mono_image_build_metadata (mb, error))
6435 if (mb->is_main && assemblyb->resources) {
6436 int len = mono_array_length (assemblyb->resources);
6437 for (i = 0; i < len; ++i) {
6438 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
6443 if (mb->resources) {
6444 int len = mono_array_length (mb->resources);
6445 for (i = 0; i < len; ++i) {
6446 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
6451 if (!build_compressed_metadata (assembly, error))
6455 assembly_add_win32_resources (assembly, assemblyb);
6457 nsections = calc_section_size (assembly);
6459 /* The DOS header and stub */
6460 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6461 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6463 /* the dotnet header */
6464 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6466 /* the section tables */
6467 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6469 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6470 virtual_offset = VIRT_ALIGN;
6473 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6474 if (!assembly->sections [i].size)
6477 file_offset += FILE_ALIGN - 1;
6478 file_offset &= ~(FILE_ALIGN - 1);
6479 virtual_offset += VIRT_ALIGN - 1;
6480 virtual_offset &= ~(VIRT_ALIGN - 1);
6482 assembly->sections [i].offset = file_offset;
6483 assembly->sections [i].rva = virtual_offset;
6485 file_offset += assembly->sections [i].size;
6486 virtual_offset += assembly->sections [i].size;
6487 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6490 file_offset += FILE_ALIGN - 1;
6491 file_offset &= ~(FILE_ALIGN - 1);
6493 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6495 /* back-patch info */
6496 msdos = (MonoMSDOSHeader*)pefile->data;
6497 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6499 header = (MonoDotNetHeader*)(pefile->data + header_start);
6500 header->pesig [0] = 'P';
6501 header->pesig [1] = 'E';
6503 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6504 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6505 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6506 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6507 if (assemblyb->pekind == 1) {
6509 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6512 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6515 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6517 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6518 header->pe.pe_major = 6;
6519 header->pe.pe_minor = 0;
6520 size = assembly->sections [MONO_SECTION_TEXT].size;
6521 size += FILE_ALIGN - 1;
6522 size &= ~(FILE_ALIGN - 1);
6523 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6524 size = assembly->sections [MONO_SECTION_RSRC].size;
6525 size += FILE_ALIGN - 1;
6526 size &= ~(FILE_ALIGN - 1);
6527 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6528 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6529 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6530 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6531 /* pe_rva_entry_point always at the beginning of the text section */
6532 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6534 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6535 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6536 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6537 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6538 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6539 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6540 size = section_start;
6541 size += FILE_ALIGN - 1;
6542 size &= ~(FILE_ALIGN - 1);
6543 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6545 size += VIRT_ALIGN - 1;
6546 size &= ~(VIRT_ALIGN - 1);
6547 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6550 // Translate the PEFileKind value to the value expected by the Windows loader
6556 // PEFileKinds.Dll == 1
6557 // PEFileKinds.ConsoleApplication == 2
6558 // PEFileKinds.WindowApplication == 3
6561 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6562 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6564 if (assemblyb->pekind == 3)
6569 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6571 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6572 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6573 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6574 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6575 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6576 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6578 /* fill data directory entries */
6580 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6581 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6583 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6584 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6586 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6587 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6588 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6589 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6590 /* patch entrypoint name */
6591 if (assemblyb->pekind == 1)
6592 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6594 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6595 /* patch imported function RVA name */
6596 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6597 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6599 /* the import table */
6600 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6601 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6602 /* patch imported dll RVA name and other entries in the dir */
6603 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6604 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6605 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6606 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6607 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6608 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6610 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6611 value = (assembly->text_rva + assembly->imp_names_offset);
6612 *p++ = (value) & 0xff;
6613 *p++ = (value >> 8) & (0xff);
6614 *p++ = (value >> 16) & (0xff);
6615 *p++ = (value >> 24) & (0xff);
6617 /* the CLI header info */
6618 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6619 cli_header->ch_size = GUINT32_FROM_LE (72);
6620 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6621 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6622 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6623 if (assemblyb->entry_point) {
6624 guint32 table_idx = 0;
6625 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6626 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6627 table_idx = methodb->table_idx;
6629 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6631 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6633 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6635 /* The embedded managed resources */
6636 text_offset = assembly->text_rva + assembly->code.index;
6637 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6638 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6639 text_offset += assembly->resources.index;
6640 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6641 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6642 text_offset += assembly->meta_size;
6643 if (assembly->strong_name_size) {
6644 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6645 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6646 text_offset += assembly->strong_name_size;
6649 /* write the section tables and section content */
6650 section = (MonoSectionTable*)(pefile->data + section_start);
6651 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6652 static const char section_names [][7] = {
6653 ".text", ".rsrc", ".reloc"
6655 if (!assembly->sections [i].size)
6657 strcpy (section->st_name, section_names [i]);
6658 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6659 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6660 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6661 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6662 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6663 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6664 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6668 checked_write_file (file, pefile->data, pefile->index);
6670 mono_dynamic_stream_reset (pefile);
6672 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6673 if (!assembly->sections [i].size)
6676 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6677 g_error ("SetFilePointer returned %d\n", GetLastError ());
6680 case MONO_SECTION_TEXT:
6681 /* patch entry point */
6682 p = (guchar*)(assembly->code.data + 2);
6683 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6684 *p++ = (value) & 0xff;
6685 *p++ = (value >> 8) & 0xff;
6686 *p++ = (value >> 16) & 0xff;
6687 *p++ = (value >> 24) & 0xff;
6689 checked_write_file (file, assembly->code.data, assembly->code.index);
6690 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6691 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6692 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6695 g_free (assembly->image.raw_metadata);
6697 case MONO_SECTION_RELOC: {
6701 guint16 type_and_offset;
6705 g_assert (sizeof (reloc) == 12);
6707 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6708 reloc.block_size = GUINT32_FROM_LE (12);
6711 * the entrypoint is always at the start of the text section
6712 * 3 is IMAGE_REL_BASED_HIGHLOW
6713 * 2 is patch_size_rva - text_rva
6715 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6718 checked_write_file (file, &reloc, sizeof (reloc));
6722 case MONO_SECTION_RSRC:
6723 if (assembly->win32_res) {
6725 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6726 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6727 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6731 g_assert_not_reached ();
6735 /* check that the file is properly padded */
6736 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6737 g_error ("SetFilePointer returned %d\n", GetLastError ());
6738 if (! SetEndOfFile (file))
6739 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6741 mono_dynamic_stream_reset (&assembly->code);
6742 mono_dynamic_stream_reset (&assembly->us);
6743 mono_dynamic_stream_reset (&assembly->blob);
6744 mono_dynamic_stream_reset (&assembly->guid);
6745 mono_dynamic_stream_reset (&assembly->sheap);
6747 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6748 g_hash_table_destroy (assembly->blob_cache);
6749 assembly->blob_cache = NULL;
6754 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6757 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6759 g_assert_not_reached ();
6762 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6764 #ifndef DISABLE_REFLECTION_EMIT
6766 MonoReflectionModule *
6767 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6771 MonoImageOpenStatus status;
6772 MonoDynamicAssembly *assembly;
6773 guint32 module_count;
6774 MonoImage **new_modules;
6775 gboolean *new_modules_loaded;
6777 mono_error_init (error);
6779 name = mono_string_to_utf8_checked (fileName, error);
6780 return_val_if_nok (error, NULL);
6782 image = mono_image_open (name, &status);
6784 if (status == MONO_IMAGE_ERROR_ERRNO)
6785 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6787 mono_error_set_bad_image_name (error, name, NULL);
6794 assembly = ab->dynamic_assembly;
6795 image->assembly = (MonoAssembly*)assembly;
6797 module_count = image->assembly->image->module_count;
6798 new_modules = g_new0 (MonoImage *, module_count + 1);
6799 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6801 if (image->assembly->image->modules)
6802 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6803 if (image->assembly->image->modules_loaded)
6804 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6805 new_modules [module_count] = image;
6806 new_modules_loaded [module_count] = TRUE;
6807 mono_image_addref (image);
6809 g_free (image->assembly->image->modules);
6810 image->assembly->image->modules = new_modules;
6811 image->assembly->image->modules_loaded = new_modules_loaded;
6812 image->assembly->image->module_count ++;
6814 mono_assembly_load_references (image, &status);
6816 mono_image_close (image);
6817 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6821 return mono_module_get_object_checked (mono_domain_get (), image, error);
6824 #endif /* DISABLE_REFLECTION_EMIT */
6827 * We need to return always the same object for MethodInfo, FieldInfo etc..
6828 * but we need to consider the reflected type.
6829 * type uses a different hash, since it uses custom hash/equal functions.
6834 MonoClass *refclass;
6838 reflected_equal (gconstpointer a, gconstpointer b) {
6839 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6840 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6842 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6846 reflected_hash (gconstpointer a) {
6847 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6848 return mono_aligned_addr_hash (ea->item);
6851 #define CHECK_OBJECT(t,p,k) \
6857 mono_domain_lock (domain); \
6858 if (!domain->refobject_hash) \
6859 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"); \
6860 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6861 mono_domain_unlock (domain); \
6864 mono_domain_unlock (domain); \
6867 #ifdef HAVE_BOEHM_GC
6868 /* ReflectedEntry doesn't need to be GC tracked */
6869 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6870 #define FREE_REFENTRY(entry) g_free ((entry))
6871 #define REFENTRY_REQUIRES_CLEANUP
6873 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6875 #define FREE_REFENTRY(entry)
6878 #define CACHE_OBJECT(t,p,o,k) \
6881 ReflectedEntry pe; \
6883 pe.refclass = (k); \
6884 mono_domain_lock (domain); \
6885 if (!domain->refobject_hash) \
6886 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"); \
6887 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6889 ReflectedEntry *e = ALLOC_REFENTRY; \
6891 e->refclass = (k); \
6892 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6895 mono_domain_unlock (domain); \
6900 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6902 mono_domain_lock (domain);
6903 if (domain->refobject_hash) {
6905 gpointer orig_pe, orig_value;
6908 pe.refclass = klass;
6909 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6910 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6911 FREE_REFENTRY (orig_pe);
6914 mono_domain_unlock (domain);
6917 #ifdef REFENTRY_REQUIRES_CLEANUP
6919 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6921 FREE_REFENTRY (key);
6926 mono_reflection_cleanup_domain (MonoDomain *domain)
6928 if (domain->refobject_hash) {
6929 /*let's avoid scanning the whole hashtable if not needed*/
6930 #ifdef REFENTRY_REQUIRES_CLEANUP
6931 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6933 mono_g_hash_table_destroy (domain->refobject_hash);
6934 domain->refobject_hash = NULL;
6938 #ifndef DISABLE_REFLECTION_EMIT
6940 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6942 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6946 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6948 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6952 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6954 MonoDynamicImage *image = moduleb->dynamic_image;
6955 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6956 mono_error_init (error);
6959 MonoImage **new_modules;
6961 char *name, *fqname;
6963 * FIXME: we already created an image in mono_image_basic_init (), but
6964 * we don't know which module it belongs to, since that is only
6965 * determined at assembly save time.
6967 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6968 name = mono_string_to_utf8_checked (ab->name, error);
6969 return_val_if_nok (error, FALSE);
6970 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6971 if (!is_ok (error)) {
6975 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6977 moduleb->module.image = &image->image;
6978 moduleb->dynamic_image = image;
6979 register_module (mono_object_domain (moduleb), moduleb, image);
6981 /* register the module with the assembly */
6982 ass = ab->dynamic_assembly->assembly.image;
6983 module_count = ass->module_count;
6984 new_modules = g_new0 (MonoImage *, module_count + 1);
6987 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6988 new_modules [module_count] = &image->image;
6989 mono_image_addref (&image->image);
6991 g_free (ass->modules);
6992 ass->modules = new_modules;
6993 ass->module_count ++;
6999 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
7002 (void) image_module_basic_init (moduleb, &error);
7003 mono_error_set_pending_exception (&error);
7007 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
7009 MonoDynamicImage *image = moduleb->dynamic_image;
7011 g_assert (type->type);
7012 image->wrappers_type = mono_class_from_mono_type (type->type);
7018 * mono_assembly_get_object:
7019 * @domain: an app domain
7020 * @assembly: an assembly
7022 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7024 MonoReflectionAssembly*
7025 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
7028 MonoReflectionAssembly *result;
7029 result = mono_assembly_get_object_checked (domain, assembly, &error);
7030 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7034 * mono_assembly_get_object_checked:
7035 * @domain: an app domain
7036 * @assembly: an assembly
7038 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7040 MonoReflectionAssembly*
7041 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7043 MonoReflectionAssembly *res;
7045 mono_error_init (error);
7047 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7048 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7051 res->assembly = assembly;
7053 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7058 MonoReflectionModule*
7059 mono_module_get_object (MonoDomain *domain, MonoImage *image)
7062 MonoReflectionModule *result;
7063 result = mono_module_get_object_checked (domain, image, &error);
7064 mono_error_cleanup (&error);
7068 MonoReflectionModule*
7069 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7071 MonoReflectionModule *res;
7074 mono_error_init (error);
7075 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7076 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7081 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7084 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7086 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7087 basename = g_path_get_basename (image->name);
7088 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7089 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7093 if (image->assembly->image == image) {
7094 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7098 if (image->assembly->image->modules) {
7099 for (i = 0; i < image->assembly->image->module_count; i++) {
7100 if (image->assembly->image->modules [i] == image)
7101 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7103 g_assert (res->token);
7107 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7110 MonoReflectionModule*
7111 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7114 MonoReflectionModule *result;
7115 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7116 mono_error_cleanup (&error);
7120 MonoReflectionModule*
7121 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7123 MonoReflectionModule *res;
7124 MonoTableInfo *table;
7125 guint32 cols [MONO_FILE_SIZE];
7127 guint32 i, name_idx;
7130 mono_error_init (error);
7132 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7136 table = &image->tables [MONO_TABLE_FILE];
7137 g_assert (table_index < table->rows);
7138 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7141 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7144 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7145 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7147 /* Check whenever the row has a corresponding row in the moduleref table */
7148 table = &image->tables [MONO_TABLE_MODULEREF];
7149 for (i = 0; i < table->rows; ++i) {
7150 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7151 val = mono_metadata_string_heap (image, name_idx);
7152 if (strcmp (val, name) == 0)
7153 res->image = image->modules [i];
7156 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7157 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7158 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7159 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7160 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7166 verify_safe_for_managed_space (MonoType *type)
7168 switch (type->type) {
7170 case MONO_TYPE_ARRAY:
7171 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7173 return verify_safe_for_managed_space (type->data.type);
7174 case MONO_TYPE_SZARRAY:
7175 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7176 case MONO_TYPE_GENERICINST: {
7177 MonoGenericInst *inst = type->data.generic_class->inst;
7181 for (i = 0; i < inst->type_argc; ++i)
7182 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7188 case MONO_TYPE_MVAR:
7196 mono_type_normalize (MonoType *type)
7199 MonoGenericClass *gclass;
7200 MonoGenericInst *ginst;
7202 MonoGenericContainer *gcontainer;
7203 MonoType **argv = NULL;
7204 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7206 if (type->type != MONO_TYPE_GENERICINST)
7209 gclass = type->data.generic_class;
7210 ginst = gclass->context.class_inst;
7211 if (!ginst->is_open)
7214 gtd = gclass->container_class;
7215 gcontainer = gtd->generic_container;
7216 argv = g_newa (MonoType*, ginst->type_argc);
7218 for (i = 0; i < ginst->type_argc; ++i) {
7219 MonoType *t = ginst->type_argv [i], *norm;
7220 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7221 is_denorm_gtd = FALSE;
7222 norm = mono_type_normalize (t);
7225 requires_rebind = TRUE;
7229 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7231 if (requires_rebind) {
7232 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7233 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7239 * mono_type_get_object:
7240 * @domain: an app domain
7243 * Return an System.MonoType object representing the type @type.
7246 mono_type_get_object (MonoDomain *domain, MonoType *type)
7249 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7250 mono_error_cleanup (&error);
7256 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7258 MonoType *norm_type;
7259 MonoReflectionType *res;
7262 mono_error_init (error);
7264 klass = mono_class_from_mono_type (type);
7266 /*we must avoid using @type as it might have come
7267 * from a mono_metadata_type_dup and the caller
7268 * expects that is can be freed.
7269 * Using the right type from
7271 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7273 /* void is very common */
7274 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7275 return (MonoReflectionType*)domain->typeof_void;
7278 * If the vtable of the given class was already created, we can use
7279 * the MonoType from there and avoid all locking and hash table lookups.
7281 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7282 * that the resulting object is different.
7284 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7285 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7286 if (vtable && vtable->type)
7287 return (MonoReflectionType *)vtable->type;
7290 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7291 mono_domain_lock (domain);
7292 if (!domain->type_hash)
7293 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7294 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7295 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7296 mono_domain_unlock (domain);
7297 mono_loader_unlock ();
7301 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7302 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7303 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7304 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7305 * artifact of how generics are encoded and should be transparent to managed code so we
7306 * need to weed out this diference when retrieving managed System.Type objects.
7308 norm_type = mono_type_normalize (type);
7309 if (norm_type != type) {
7310 res = mono_type_get_object_checked (domain, norm_type, error);
7311 if (!mono_error_ok (error))
7313 mono_g_hash_table_insert (domain->type_hash, type, res);
7314 mono_domain_unlock (domain);
7315 mono_loader_unlock ();
7319 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7320 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7323 if (!verify_safe_for_managed_space (type)) {
7324 mono_domain_unlock (domain);
7325 mono_loader_unlock ();
7326 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7330 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7331 gboolean is_type_done = TRUE;
7332 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7333 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7334 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7336 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7337 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7339 if (gparam->owner && gparam->owner->is_method) {
7340 MonoMethod *method = gparam->owner->owner.method;
7341 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7342 is_type_done = FALSE;
7343 } else if (gparam->owner && !gparam->owner->is_method) {
7344 MonoClass *klass = gparam->owner->owner.klass;
7345 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7346 is_type_done = FALSE;
7350 /* g_assert_not_reached (); */
7351 /* should this be considered an error condition? */
7352 if (is_type_done && !type->byref) {
7353 mono_domain_unlock (domain);
7354 mono_loader_unlock ();
7355 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7358 /* This is stored in vtables/JITted code so it has to be pinned */
7359 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7360 if (!mono_error_ok (error))
7364 mono_g_hash_table_insert (domain->type_hash, type, res);
7366 if (type->type == MONO_TYPE_VOID)
7367 domain->typeof_void = (MonoObject*)res;
7369 mono_domain_unlock (domain);
7370 mono_loader_unlock ();
7375 * mono_method_get_object:
7376 * @domain: an app domain
7378 * @refclass: the reflected type (can be NULL)
7380 * Return an System.Reflection.MonoMethod object representing the method @method.
7382 MonoReflectionMethod*
7383 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7386 MonoReflectionMethod *ret = NULL;
7387 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7388 mono_error_cleanup (&error);
7393 * mono_method_get_object_checked:
7394 * @domain: an app domain
7396 * @refclass: the reflected type (can be NULL)
7397 * @error: set on error.
7399 * Return an System.Reflection.MonoMethod object representing the method @method.
7400 * Returns NULL and sets @error on error.
7402 MonoReflectionMethod*
7403 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7406 * We use the same C representation for methods and constructors, but the type
7407 * name in C# is different.
7409 MonoReflectionType *rt;
7411 MonoReflectionMethod *ret;
7413 mono_error_init (error);
7415 if (method->is_inflated) {
7416 MonoReflectionGenericMethod *gret;
7419 refclass = method->klass;
7420 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7421 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7422 klass = mono_class_get_mono_generic_cmethod_class ();
7424 klass = mono_class_get_mono_generic_method_class ();
7426 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7427 if (!mono_error_ok (error))
7429 gret->method.method = method;
7431 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7433 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7434 if (!mono_error_ok (error))
7437 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7439 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7443 refclass = method->klass;
7445 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7446 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7447 klass = mono_class_get_mono_cmethod_class ();
7450 klass = mono_class_get_mono_method_class ();
7452 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7453 if (!mono_error_ok (error))
7455 ret->method = method;
7457 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7458 if (!mono_error_ok (error))
7461 MONO_OBJECT_SETREF (ret, reftype, rt);
7463 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7466 g_assert (!mono_error_ok (error));
7471 * mono_method_clear_object:
7473 * Clear the cached reflection objects for the dynamic method METHOD.
7476 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7479 g_assert (method_is_dynamic (method));
7481 klass = method->klass;
7483 clear_cached_object (domain, method, klass);
7484 klass = klass->parent;
7486 /* Added by mono_param_get_objects () */
7487 clear_cached_object (domain, &(method->signature), NULL);
7488 klass = method->klass;
7490 clear_cached_object (domain, &(method->signature), klass);
7491 klass = klass->parent;
7496 * mono_field_get_object:
7497 * @domain: an app domain
7501 * Return an System.Reflection.MonoField object representing the field @field
7504 MonoReflectionField*
7505 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7508 MonoReflectionField *result;
7509 result = mono_field_get_object_checked (domain, klass, field, &error);
7510 mono_error_cleanup (&error);
7515 * mono_field_get_object_checked:
7516 * @domain: an app domain
7519 * @error: set on error
7521 * Return an System.Reflection.MonoField object representing the field @field
7522 * in class @klass. On error, returns NULL and sets @error.
7524 MonoReflectionField*
7525 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7527 MonoReflectionType *rt;
7528 MonoReflectionField *res;
7530 mono_error_init (error);
7532 CHECK_OBJECT (MonoReflectionField *, field, klass);
7533 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7538 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7540 if (is_field_on_inst (field)) {
7541 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7543 rt = mono_type_get_object_checked (domain, field->type, error);
7544 if (!mono_error_ok (error))
7547 MONO_OBJECT_SETREF (res, type, rt);
7550 rt = mono_type_get_object_checked (domain, field->type, error);
7551 if (!mono_error_ok (error))
7554 MONO_OBJECT_SETREF (res, type, rt);
7556 res->attrs = mono_field_get_flags (field);
7558 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7562 * mono_property_get_object:
7563 * @domain: an app domain
7565 * @property: a property
7567 * Return an System.Reflection.MonoProperty object representing the property @property
7570 MonoReflectionProperty*
7571 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7574 MonoReflectionProperty *result;
7575 result = mono_property_get_object_checked (domain, klass, property, &error);
7576 mono_error_cleanup (&error);
7581 * mono_property_get_object:
7582 * @domain: an app domain
7584 * @property: a property
7585 * @error: set on error
7587 * Return an System.Reflection.MonoProperty object representing the property @property
7588 * in class @klass. On error returns NULL and sets @error.
7590 MonoReflectionProperty*
7591 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7593 MonoReflectionProperty *res;
7595 mono_error_init (error);
7597 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7598 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7602 res->property = property;
7603 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7607 * mono_event_get_object:
7608 * @domain: an app domain
7612 * Return an System.Reflection.MonoEvent object representing the event @event
7615 MonoReflectionEvent*
7616 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7619 MonoReflectionEvent *result;
7620 result = mono_event_get_object_checked (domain, klass, event, &error);
7621 mono_error_cleanup (&error);
7626 * mono_event_get_object_checked:
7627 * @domain: an app domain
7630 * @error: set on error
7632 * Return an System.Reflection.MonoEvent object representing the event @event
7633 * in class @klass. On failure sets @error and returns NULL
7635 MonoReflectionEvent*
7636 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7638 MonoReflectionEvent *res;
7639 MonoReflectionMonoEvent *mono_event;
7641 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7642 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7645 mono_event->klass = klass;
7646 mono_event->event = event;
7647 res = (MonoReflectionEvent*)mono_event;
7648 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7652 * mono_get_reflection_missing_object:
7653 * @domain: Domain where the object lives
7655 * Returns the System.Reflection.Missing.Value singleton object
7656 * (of type System.Reflection.Missing).
7658 * Used as the value for ParameterInfo.DefaultValue when Optional
7662 mono_get_reflection_missing_object (MonoDomain *domain)
7666 static MonoClassField *missing_value_field = NULL;
7668 if (!missing_value_field) {
7669 MonoClass *missing_klass;
7670 missing_klass = mono_class_get_missing_class ();
7671 mono_class_init (missing_klass);
7672 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7673 g_assert (missing_value_field);
7675 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7676 mono_error_assert_ok (&error);
7681 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7684 *dbnull = mono_get_dbnull_object (domain);
7689 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7691 if (!*reflection_missing)
7692 *reflection_missing = mono_get_reflection_missing_object (domain);
7693 return *reflection_missing;
7697 * mono_param_get_objects:
7698 * @domain: an app domain
7701 * Return an System.Reflection.ParameterInfo array object representing the parameters
7702 * in the method @method.
7705 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7707 static MonoClass *System_Reflection_ParameterInfo;
7708 static MonoClass *System_Reflection_ParameterInfo_array;
7709 MonoArray *res = NULL;
7710 MonoReflectionMethod *member = NULL;
7711 MonoReflectionParameter *param = NULL;
7712 char **names = NULL, **blobs = NULL;
7713 guint32 *types = NULL;
7714 MonoType *type = NULL;
7715 MonoObject *dbnull = NULL;
7716 MonoObject *missing = NULL;
7717 MonoMarshalSpec **mspecs = NULL;
7718 MonoMethodSignature *sig = NULL;
7719 MonoVTable *pinfo_vtable;
7720 MonoReflectionType *rt;
7723 mono_error_init (error);
7725 if (!System_Reflection_ParameterInfo_array) {
7728 klass = mono_class_get_mono_parameter_info_class ();
7730 mono_memory_barrier ();
7731 System_Reflection_ParameterInfo = klass;
7734 klass = mono_array_class_get (klass, 1);
7735 mono_memory_barrier ();
7736 System_Reflection_ParameterInfo_array = klass;
7739 sig = mono_method_signature_checked (method, error);
7740 if (!mono_error_ok (error))
7743 if (!sig->param_count) {
7744 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7751 /* Note: the cache is based on the address of the signature into the method
7752 * since we already cache MethodInfos with the method as keys.
7754 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7756 member = mono_method_get_object_checked (domain, method, refclass, error);
7759 names = g_new (char *, sig->param_count);
7760 mono_method_get_param_names (method, (const char **) names);
7762 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7763 mono_method_get_marshal_info (method, mspecs);
7765 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7769 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7770 for (i = 0; i < sig->param_count; ++i) {
7771 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7775 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7779 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7781 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7783 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7785 param->PositionImpl = i;
7786 param->AttrsImpl = sig->params [i]->attrs;
7788 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7789 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7790 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7792 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7796 blobs = g_new0 (char *, sig->param_count);
7797 types = g_new0 (guint32, sig->param_count);
7798 get_default_param_value_blobs (method, blobs, types);
7801 /* Build MonoType for the type from the Constant Table */
7803 type = g_new0 (MonoType, 1);
7804 type->type = (MonoTypeEnum)types [i];
7805 type->data.klass = NULL;
7806 if (types [i] == MONO_TYPE_CLASS)
7807 type->data.klass = mono_defaults.object_class;
7808 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7809 /* For enums, types [i] contains the base type */
7811 type->type = MONO_TYPE_VALUETYPE;
7812 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7814 type->data.klass = mono_class_from_mono_type (type);
7816 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7819 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7821 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7822 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7823 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7824 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7826 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7831 if (mspecs [i + 1]) {
7832 MonoReflectionMarshalAsAttribute* mobj;
7833 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7836 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7839 mono_array_setref (res, i, param);
7849 for (i = sig->param_count; i >= 0; i--) {
7851 mono_metadata_free_marshal_spec (mspecs [i]);
7859 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7863 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7866 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7867 mono_error_assert_ok (&error);
7872 * mono_method_body_get_object:
7873 * @domain: an app domain
7876 * Return an System.Reflection.MethodBody object representing the method @method.
7878 MonoReflectionMethodBody*
7879 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7882 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7883 mono_error_cleanup (&error);
7888 * mono_method_body_get_object_checked:
7889 * @domain: an app domain
7891 * @error: set on error
7893 * Return an System.Reflection.MethodBody object representing the
7894 * method @method. On failure, returns NULL and sets @error.
7896 MonoReflectionMethodBody*
7897 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7899 MonoReflectionMethodBody *ret;
7900 MonoMethodHeader *header;
7902 MonoReflectionType *rt;
7903 guint32 method_rva, local_var_sig_token;
7905 unsigned char format, flags;
7908 mono_error_init (error);
7910 /* for compatibility with .net */
7911 if (method_is_dynamic (method)) {
7912 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7916 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7918 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7919 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7920 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7921 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7922 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7925 image = method->klass->image;
7926 header = mono_method_get_header_checked (method, error);
7927 return_val_if_nok (error, NULL);
7929 if (!image_is_dynamic (image)) {
7930 /* Obtain local vars signature token */
7931 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7932 ptr = mono_image_rva_map (image, method_rva);
7933 flags = *(const unsigned char *) ptr;
7934 format = flags & METHOD_HEADER_FORMAT_MASK;
7936 case METHOD_HEADER_TINY_FORMAT:
7937 local_var_sig_token = 0;
7939 case METHOD_HEADER_FAT_FORMAT:
7943 local_var_sig_token = read32 (ptr);
7946 g_assert_not_reached ();
7949 local_var_sig_token = 0; //FIXME
7951 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7955 ret->init_locals = header->init_locals;
7956 ret->max_stack = header->max_stack;
7957 ret->local_var_sig_token = local_var_sig_token;
7958 MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7961 MONO_OBJECT_SETREF (ret, il, il_arr);
7962 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7965 MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7968 MONO_OBJECT_SETREF (ret, locals, locals_arr);
7969 for (i = 0; i < header->num_locals; ++i) {
7970 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7974 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7978 MONO_OBJECT_SETREF (info, local_type, rt);
7980 info->is_pinned = header->locals [i]->pinned;
7981 info->local_index = i;
7982 mono_array_setref (ret->locals, i, info);
7986 MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7989 MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7990 for (i = 0; i < header->num_clauses; ++i) {
7991 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7994 MonoExceptionClause *clause = &header->clauses [i];
7996 info->flags = clause->flags;
7997 info->try_offset = clause->try_offset;
7998 info->try_length = clause->try_len;
7999 info->handler_offset = clause->handler_offset;
8000 info->handler_length = clause->handler_len;
8001 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8002 info->filter_offset = clause->data.filter_offset;
8003 else if (clause->data.catch_class) {
8004 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
8008 MONO_OBJECT_SETREF (info, catch_type, rt);
8011 mono_array_setref (ret->clauses, i, info);
8014 mono_metadata_free_mh (header);
8015 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
8019 mono_metadata_free_mh (header);
8024 * mono_get_dbnull_object:
8025 * @domain: Domain where the object lives
8027 * Returns the System.DBNull.Value singleton object
8029 * Used as the value for ParameterInfo.DefaultValue
8032 mono_get_dbnull_object (MonoDomain *domain)
8036 static MonoClassField *dbnull_value_field = NULL;
8038 if (!dbnull_value_field) {
8039 MonoClass *dbnull_klass;
8040 dbnull_klass = mono_class_get_dbnull_class ();
8041 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8042 g_assert (dbnull_value_field);
8044 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8045 mono_error_assert_ok (&error);
8050 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8052 guint32 param_index, i, lastp, crow = 0;
8053 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8056 MonoClass *klass = method->klass;
8057 MonoImage *image = klass->image;
8058 MonoMethodSignature *methodsig = mono_method_signature (method);
8060 MonoTableInfo *constt;
8061 MonoTableInfo *methodt;
8062 MonoTableInfo *paramt;
8064 if (!methodsig->param_count)
8067 mono_class_init (klass);
8069 if (image_is_dynamic (klass->image)) {
8070 MonoReflectionMethodAux *aux;
8071 if (method->is_inflated)
8072 method = ((MonoMethodInflated*)method)->declaring;
8073 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8074 if (aux && aux->param_defaults) {
8075 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8076 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8081 methodt = &klass->image->tables [MONO_TABLE_METHOD];
8082 paramt = &klass->image->tables [MONO_TABLE_PARAM];
8083 constt = &image->tables [MONO_TABLE_CONSTANT];
8085 idx = mono_method_get_index (method) - 1;
8086 g_assert (idx != -1);
8088 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8089 if (idx + 1 < methodt->rows)
8090 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8092 lastp = paramt->rows + 1;
8094 for (i = param_index; i < lastp; ++i) {
8097 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8098 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8100 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8103 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8108 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8109 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8110 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8117 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8122 MonoType *basetype = type;
8124 mono_error_init (error);
8129 klass = mono_class_from_mono_type (type);
8130 if (klass->valuetype) {
8131 object = mono_object_new_checked (domain, klass, error);
8132 return_val_if_nok (error, NULL);
8133 retval = ((gchar *) object + sizeof (MonoObject));
8134 if (klass->enumtype)
8135 basetype = mono_class_enum_basetype (klass);
8140 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
8147 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8150 gboolean quoted = FALSE;
8152 memset (assembly, 0, sizeof (MonoAssemblyName));
8153 assembly->culture = "";
8154 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8161 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8172 /* Remove trailing whitespace */
8174 while (*s && g_ascii_isspace (*s))
8177 while (g_ascii_isspace (*p))
8180 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8182 assembly->major = strtoul (p, &s, 10);
8183 if (s == p || *s != '.')
8186 assembly->minor = strtoul (p, &s, 10);
8187 if (s == p || *s != '.')
8190 assembly->build = strtoul (p, &s, 10);
8191 if (s == p || *s != '.')
8194 assembly->revision = strtoul (p, &s, 10);
8198 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8200 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8201 assembly->culture = "";
8204 assembly->culture = p;
8205 while (*p && *p != ',') {
8209 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8211 if (strncmp (p, "null", 4) == 0) {
8216 while (*p && *p != ',') {
8219 len = (p - start + 1);
8220 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8221 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8222 g_strlcpy ((char*)assembly->public_key_token, start, len);
8225 while (*p && *p != ',')
8229 while (g_ascii_isspace (*p) || *p == ',') {
8243 * mono_reflection_parse_type:
8246 * Parse a type name as accepted by the GetType () method and output the info
8247 * extracted in the info structure.
8248 * the name param will be mangled, so, make a copy before passing it to this function.
8249 * The fields in info will be valid until the memory pointed to by name is valid.
8251 * See also mono_type_get_name () below.
8253 * Returns: 0 on parse error.
8256 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8257 MonoTypeNameParse *info)
8259 char *start, *p, *w, *last_point, *startn;
8260 int in_modifiers = 0;
8261 int isbyref = 0, rank = 0, isptr = 0;
8263 start = p = w = name;
8265 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8266 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8267 info->name = info->name_space = NULL;
8268 info->nested = NULL;
8269 info->modifiers = NULL;
8270 info->type_arguments = NULL;
8272 /* last_point separates the namespace from the name */
8275 while (*p == ' ') p++, start++, w++, name++;
8280 *p = 0; /* NULL terminate the name */
8282 info->nested = g_list_append (info->nested, startn);
8283 /* we have parsed the nesting namespace + name */
8287 info->name_space = start;
8289 info->name = last_point + 1;
8291 info->name_space = (char *)"";
8319 info->name_space = start;
8321 info->name = last_point + 1;
8323 info->name_space = (char *)"";
8330 if (isbyref) /* only one level allowed by the spec */
8334 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8338 if (isbyref) /* pointer to ref not okay */
8340 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8345 if (isbyref) /* array of ref and generic ref are not okay */
8347 //Decide if it's an array of a generic argument list
8352 if (*p == ',' || *p == '*' || *p == ']') { //array
8360 else if (*p == '*') /* '*' means unknown lower bound */
8361 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8368 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8370 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8373 info->type_arguments = g_ptr_array_new ();
8375 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8376 gboolean fqname = FALSE;
8378 g_ptr_array_add (info->type_arguments, subinfo);
8380 while (*p == ' ') p++;
8386 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8389 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8390 if (fqname && (*p != ']')) {
8398 while (*p && (*p != ']'))
8406 if (g_ascii_isspace (*aname)) {
8413 !assembly_name_to_aname (&subinfo->assembly, aname))
8415 } else if (fqname && (*p == ']')) {
8437 if (g_ascii_isspace (*p)) {
8444 return 0; /* missing assembly name */
8445 if (!assembly_name_to_aname (&info->assembly, p))
8451 if (info->assembly.name)
8454 // *w = 0; /* terminate class name */
8456 if (!info->name || !*info->name)
8460 /* add other consistency checks */
8466 * mono_identifier_unescape_type_name_chars:
8467 * @identifier: the display name of a mono type
8470 * The name in internal form, that is without escaping backslashes.
8472 * The string is modified in place!
8475 mono_identifier_unescape_type_name_chars(char* identifier)
8480 for (w = r = identifier; *r != 0; r++)
8498 mono_identifier_unescape_info (MonoTypeNameParse* info);
8501 unescape_each_type_argument(void* data, void* user_data)
8503 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8504 mono_identifier_unescape_info (info);
8508 unescape_each_nested_name (void* data, void* user_data)
8510 char* nested_name = (char*) data;
8511 mono_identifier_unescape_type_name_chars(nested_name);
8515 * mono_identifier_unescape_info:
8517 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8521 * Destructively updates the info by unescaping the identifiers that
8522 * comprise the type namespace, name, nested types (if any) and
8523 * generic type arguments (if any).
8525 * The resulting info has the names in internal form.
8529 mono_identifier_unescape_info (MonoTypeNameParse *info)
8533 mono_identifier_unescape_type_name_chars(info->name_space);
8534 mono_identifier_unescape_type_name_chars(info->name);
8535 // but don't escape info->assembly
8536 if (info->type_arguments)
8537 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8539 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8543 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8545 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8547 mono_identifier_unescape_info (info);
8553 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8555 gboolean type_resolve = FALSE;
8557 MonoImage *rootimage = image;
8559 mono_error_init (error);
8561 if (info->assembly.name) {
8562 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8563 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8565 * This could happen in the AOT compiler case when the search hook is not
8568 assembly = image->assembly;
8570 /* then we must load the assembly ourselve - see #60439 */
8571 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8575 image = assembly->image;
8576 } else if (!image) {
8577 image = mono_defaults.corlib;
8580 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8581 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8582 /* ignore the error and try again */
8583 mono_error_cleanup (error);
8584 mono_error_init (error);
8585 image = mono_defaults.corlib;
8586 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8593 * mono_reflection_get_type_internal:
8595 * Returns: may return NULL on success, sets error on failure.
8598 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8603 gboolean bounded = FALSE;
8605 mono_error_init (error);
8607 image = mono_defaults.corlib;
8610 rootimage = mono_defaults.corlib;
8613 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8615 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8620 for (mod = info->nested; mod; mod = mod->next) {
8621 gpointer iter = NULL;
8625 mono_class_init (parent);
8627 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8629 char *nested_name, *nested_nspace;
8630 gboolean match = TRUE;
8632 lastp = strrchr ((const char *)mod->data, '.');
8634 /* Nested classes can have namespaces */
8637 nested_name = g_strdup (lastp + 1);
8638 nspace_len = lastp - (char*)mod->data;
8639 nested_nspace = (char *)g_malloc (nspace_len + 1);
8640 memcpy (nested_nspace, mod->data, nspace_len);
8641 nested_nspace [nspace_len] = '\0';
8644 nested_name = (char *)mod->data;
8645 nested_nspace = NULL;
8648 if (nested_nspace) {
8650 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8653 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8659 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8662 if (strcmp (klass->name, nested_name) != 0)
8667 g_free (nested_name);
8668 g_free (nested_nspace);
8680 if (info->type_arguments) {
8681 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8682 MonoReflectionType *the_type;
8686 for (i = 0; i < info->type_arguments->len; i++) {
8687 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8689 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8690 if (!type_args [i]) {
8696 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8700 instance = mono_reflection_bind_generic_parameters (
8701 the_type, info->type_arguments->len, type_args, error);
8707 klass = mono_class_from_mono_type (instance);
8710 for (mod = info->modifiers; mod; mod = mod->next) {
8711 modval = GPOINTER_TO_UINT (mod->data);
8712 if (!modval) { /* byref: must be last modifier */
8713 return &klass->this_arg;
8714 } else if (modval == -1) {
8715 klass = mono_ptr_class_get (&klass->byval_arg);
8716 } else if (modval == -2) {
8718 } else { /* array rank */
8719 klass = mono_bounded_array_class_get (klass, modval, bounded);
8723 return &klass->byval_arg;
8727 * mono_reflection_get_type:
8728 * @image: a metadata context
8729 * @info: type description structure
8730 * @ignorecase: flag for case-insensitive string compares
8731 * @type_resolve: whenever type resolve was already tried
8733 * Build a MonoType from the type description in @info.
8738 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8740 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8741 mono_error_cleanup (&error);
8746 * mono_reflection_get_type_checked:
8747 * @rootimage: the image of the currently active managed caller
8748 * @image: a metadata context
8749 * @info: type description structure
8750 * @ignorecase: flag for case-insensitive string compares
8751 * @type_resolve: whenever type resolve was already tried
8752 * @error: set on error.
8754 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8758 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8759 mono_error_init (error);
8760 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8765 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8767 MonoReflectionAssemblyBuilder *abuilder;
8771 mono_error_init (error);
8772 g_assert (assembly_is_dynamic (assembly));
8773 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8777 /* Enumerate all modules */
8780 if (abuilder->modules) {
8781 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8782 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8783 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8786 if (!mono_error_ok (error))
8791 if (!type && abuilder->loaded_modules) {
8792 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8793 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8794 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8797 if (!mono_error_ok (error))
8806 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8809 MonoReflectionAssembly *assembly;
8813 mono_error_init (error);
8815 if (image && image_is_dynamic (image))
8816 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8818 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8820 return_val_if_nok (error, NULL);
8824 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8831 *type_resolve = TRUE;
8834 /* Reconstruct the type name */
8835 fullName = g_string_new ("");
8836 if (info->name_space && (info->name_space [0] != '\0'))
8837 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8839 g_string_printf (fullName, "%s", info->name);
8840 for (mod = info->nested; mod; mod = mod->next)
8841 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8843 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8844 if (!is_ok (error)) {
8845 g_string_free (fullName, TRUE);
8850 if (assembly_is_dynamic (assembly->assembly))
8851 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8852 info, ignorecase, error);
8854 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8855 info, ignorecase, error);
8857 g_string_free (fullName, TRUE);
8858 return_val_if_nok (error, NULL);
8863 mono_reflection_free_type_info (MonoTypeNameParse *info)
8865 g_list_free (info->modifiers);
8866 g_list_free (info->nested);
8868 if (info->type_arguments) {
8871 for (i = 0; i < info->type_arguments->len; i++) {
8872 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8874 mono_reflection_free_type_info (subinfo);
8875 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8879 g_ptr_array_free (info->type_arguments, TRUE);
8884 * mono_reflection_type_from_name:
8886 * @image: a metadata context (can be NULL).
8888 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8889 * it defaults to get the type from @image or, if @image is NULL or loading
8890 * from it fails, uses corlib.
8894 mono_reflection_type_from_name (char *name, MonoImage *image)
8897 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8898 mono_error_cleanup (&error);
8903 * mono_reflection_type_from_name_checked:
8905 * @image: a metadata context (can be NULL).
8906 * @error: set on errror.
8908 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8909 * it defaults to get the type from @image or, if @image is NULL or loading
8910 * from it fails, uses corlib. On failure returns NULL and sets @error.
8914 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8916 MonoType *type = NULL;
8917 MonoTypeNameParse info;
8920 mono_error_init (error);
8921 /* Make a copy since parse_type modifies its argument */
8922 tmp = g_strdup (name);
8924 /*g_print ("requested type %s\n", str);*/
8925 if (mono_reflection_parse_type (tmp, &info)) {
8926 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8927 if (!is_ok (error)) {
8929 mono_reflection_free_type_info (&info);
8935 mono_reflection_free_type_info (&info);
8940 * mono_reflection_get_token:
8942 * Return the metadata token of OBJ which should be an object
8943 * representing a metadata element.
8946 mono_reflection_get_token (MonoObject *obj)
8949 guint32 result = mono_reflection_get_token_checked (obj, &error);
8950 mono_error_assert_ok (&error);
8955 * mono_reflection_get_token_checked:
8957 * @error: set on error
8959 * Return the metadata token of @obj which should be an object
8960 * representing a metadata element. On failure sets @error.
8963 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8968 mono_error_init (error);
8970 klass = obj->vtable->klass;
8972 if (strcmp (klass->name, "MethodBuilder") == 0) {
8973 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8975 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8976 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8977 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8979 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8980 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8981 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8983 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8984 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8985 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8986 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8987 } else if (strcmp (klass->name, "RuntimeType") == 0) {
8988 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8989 return_val_if_nok (error, 0);
8990 MonoClass *mc = mono_class_from_mono_type (type);
8991 if (!mono_class_init (mc)) {
8992 mono_error_set_for_class_failure (error, mc);
8996 token = mc->type_token;
8997 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8998 strcmp (klass->name, "MonoMethod") == 0 ||
8999 strcmp (klass->name, "MonoGenericMethod") == 0 ||
9000 strcmp (klass->name, "MonoGenericCMethod") == 0) {
9001 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
9002 if (m->method->is_inflated) {
9003 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
9004 return inflated->declaring->token;
9006 token = m->method->token;
9008 } else if (strcmp (klass->name, "MonoField") == 0) {
9009 MonoReflectionField *f = (MonoReflectionField*)obj;
9011 if (is_field_on_inst (f->field)) {
9012 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
9014 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
9015 int field_index = f->field - dgclass->fields;
9018 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
9019 obj = dgclass->field_objects [field_index];
9020 return mono_reflection_get_token_checked (obj, error);
9023 token = mono_class_get_field_token (f->field);
9024 } else if (strcmp (klass->name, "MonoProperty") == 0) {
9025 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
9027 token = mono_class_get_property_token (p->property);
9028 } else if (strcmp (klass->name, "MonoEvent") == 0) {
9029 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
9031 token = mono_class_get_event_token (p->event);
9032 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
9033 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
9034 MonoClass *member_class = mono_object_class (p->MemberImpl);
9035 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
9037 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
9038 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
9039 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9042 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9043 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9045 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9046 klass->name_space, klass->name);
9054 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
9055 * The @is_enum flag only affects the error message that's displayed on failure.
9058 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9060 MonoError inner_error;
9061 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9063 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9064 "Could not load %s %s while decoding custom attribute: %s",
9065 is_enum ? "enum type": "type",
9067 mono_error_get_message (&inner_error));
9068 mono_error_cleanup (&inner_error);
9075 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9079 int slen = mono_metadata_decode_value (p, &p);
9081 mono_error_init (error);
9083 n = (char *)g_memdup (p, slen + 1);
9085 t = cattr_type_from_name (n, image, TRUE, error);
9087 return_val_if_nok (error, NULL);
9090 return mono_class_from_mono_type (t);
9094 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9096 int slen, type = t->type;
9097 MonoClass *tklass = t->data.klass;
9099 mono_error_init (error);
9105 case MONO_TYPE_BOOLEAN: {
9106 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9111 case MONO_TYPE_CHAR:
9113 case MONO_TYPE_I2: {
9114 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9119 #if SIZEOF_VOID_P == 4
9125 case MONO_TYPE_I4: {
9126 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9131 #if SIZEOF_VOID_P == 8
9132 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9136 case MONO_TYPE_I8: {
9137 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9142 case MONO_TYPE_R8: {
9143 double *val = (double *)g_malloc (sizeof (double));
9148 case MONO_TYPE_VALUETYPE:
9149 if (t->data.klass->enumtype) {
9150 type = mono_class_enum_basetype (t->data.klass)->type;
9153 MonoClass *k = t->data.klass;
9155 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9156 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9162 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9165 case MONO_TYPE_STRING:
9166 if (*p == (char)0xFF) {
9170 slen = mono_metadata_decode_value (p, &p);
9172 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9173 case MONO_TYPE_CLASS: {
9174 MonoReflectionType *rt;
9177 if (*p == (char)0xFF) {
9182 slen = mono_metadata_decode_value (p, &p);
9183 n = (char *)g_memdup (p, slen + 1);
9185 t = cattr_type_from_name (n, image, FALSE, error);
9187 return_val_if_nok (error, NULL);
9190 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9191 if (!mono_error_ok (error))
9196 case MONO_TYPE_OBJECT: {
9199 MonoClass *subc = NULL;
9204 } else if (subt == 0x0E) {
9205 type = MONO_TYPE_STRING;
9207 } else if (subt == 0x1D) {
9208 MonoType simple_type = {{0}};
9212 type = MONO_TYPE_SZARRAY;
9213 if (etype == 0x50) {
9214 tklass = mono_defaults.systemtype_class;
9215 } else if (etype == 0x55) {
9216 tklass = load_cattr_enum_type (image, p, &p, error);
9217 if (!mono_error_ok (error))
9221 /* See Partition II, Appendix B3 */
9222 etype = MONO_TYPE_OBJECT;
9223 simple_type.type = (MonoTypeEnum)etype;
9224 tklass = mono_class_from_mono_type (&simple_type);
9227 } else if (subt == 0x55) {
9230 slen = mono_metadata_decode_value (p, &p);
9231 n = (char *)g_memdup (p, slen + 1);
9233 t = cattr_type_from_name (n, image, FALSE, error);
9235 return_val_if_nok (error, NULL);
9237 subc = mono_class_from_mono_type (t);
9238 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9239 MonoType simple_type = {{0}};
9240 simple_type.type = (MonoTypeEnum)subt;
9241 subc = mono_class_from_mono_type (&simple_type);
9243 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9245 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9247 if (mono_error_ok (error)) {
9248 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9249 g_assert (!subc->has_references);
9250 if (mono_error_ok (error))
9251 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9257 case MONO_TYPE_SZARRAY: {
9259 guint32 i, alen, basetype;
9262 if (alen == 0xffffffff) {
9266 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9267 return_val_if_nok (error, NULL);
9268 basetype = tklass->byval_arg.type;
9269 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9270 basetype = mono_class_enum_basetype (tklass)->type;
9275 case MONO_TYPE_BOOLEAN:
9276 for (i = 0; i < alen; i++) {
9277 MonoBoolean val = *p++;
9278 mono_array_set (arr, MonoBoolean, i, val);
9281 case MONO_TYPE_CHAR:
9284 for (i = 0; i < alen; i++) {
9285 guint16 val = read16 (p);
9286 mono_array_set (arr, guint16, i, val);
9293 for (i = 0; i < alen; i++) {
9294 guint32 val = read32 (p);
9295 mono_array_set (arr, guint32, i, val);
9300 for (i = 0; i < alen; i++) {
9303 mono_array_set (arr, double, i, val);
9309 for (i = 0; i < alen; i++) {
9310 guint64 val = read64 (p);
9311 mono_array_set (arr, guint64, i, val);
9315 case MONO_TYPE_CLASS:
9316 case MONO_TYPE_OBJECT:
9317 case MONO_TYPE_STRING:
9318 case MONO_TYPE_SZARRAY:
9319 for (i = 0; i < alen; i++) {
9320 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9321 if (!mono_error_ok (error))
9323 mono_array_setref (arr, i, item);
9327 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9333 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9339 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9341 mono_error_init (error);
9343 gboolean is_ref = type_is_reference (t);
9345 void *val = load_cattr_value (image, t, p, end, error);
9346 if (!is_ok (error)) {
9353 return (MonoObject*)val;
9355 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9361 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9363 static MonoMethod *ctor;
9365 void *params [2], *unboxed;
9367 mono_error_init (error);
9370 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9372 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9373 return_val_if_nok (error, NULL);
9376 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9377 return_val_if_nok (error, NULL);
9378 unboxed = mono_object_unbox (retval);
9380 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9381 return_val_if_nok (error, NULL);
9387 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9389 static MonoMethod *ctor;
9391 void *unboxed, *params [2];
9393 mono_error_init (error);
9396 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9399 params [1] = typedarg;
9400 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9401 return_val_if_nok (error, NULL);
9403 unboxed = mono_object_unbox (retval);
9405 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9406 return_val_if_nok (error, NULL);
9412 type_is_reference (MonoType *type)
9414 switch (type->type) {
9415 case MONO_TYPE_BOOLEAN:
9416 case MONO_TYPE_CHAR:
9429 case MONO_TYPE_VALUETYPE:
9437 free_param_data (MonoMethodSignature *sig, void **params) {
9439 for (i = 0; i < sig->param_count; ++i) {
9440 if (!type_is_reference (sig->params [i]))
9441 g_free (params [i]);
9446 * Find the field index in the metadata FieldDef table.
9449 find_field_index (MonoClass *klass, MonoClassField *field) {
9452 for (i = 0; i < klass->field.count; ++i) {
9453 if (field == &klass->fields [i])
9454 return klass->field.first + 1 + i;
9460 * Find the property index in the metadata Property table.
9463 find_property_index (MonoClass *klass, MonoProperty *property) {
9466 for (i = 0; i < klass->ext->property.count; ++i) {
9467 if (property == &klass->ext->properties [i])
9468 return klass->ext->property.first + 1 + i;
9474 * Find the event index in the metadata Event table.
9477 find_event_index (MonoClass *klass, MonoEvent *event) {
9480 for (i = 0; i < klass->ext->event.count; ++i) {
9481 if (event == &klass->ext->events [i])
9482 return klass->ext->event.first + 1 + i;
9488 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9490 const char *p = (const char*)data;
9492 guint32 i, j, num_named;
9494 void *params_buf [32];
9495 void **params = NULL;
9496 MonoMethodSignature *sig;
9498 mono_error_init (error);
9500 mono_class_init (method->klass);
9502 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9503 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9508 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9509 if (!mono_error_ok (error)) return NULL;
9511 mono_runtime_invoke_checked (method, attr, NULL, error);
9512 if (!mono_error_ok (error))
9518 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9521 /*g_print ("got attr %s\n", method->klass->name);*/
9523 sig = mono_method_signature (method);
9524 if (sig->param_count < 32) {
9525 params = params_buf;
9526 memset (params, 0, sizeof (void*) * sig->param_count);
9528 /* Allocate using GC so it gets GC tracking */
9529 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9534 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9535 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9536 if (!mono_error_ok (error))
9541 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9542 if (!mono_error_ok (error)) goto fail;
9544 MonoObject *exc = NULL;
9545 mono_runtime_try_invoke (method, attr, params, &exc, error);
9546 if (!mono_error_ok (error))
9549 mono_error_set_exception_instance (error, (MonoException*)exc);
9553 num_named = read16 (named);
9555 for (j = 0; j < num_named; j++) {
9557 char *name, named_type, data_type;
9558 named_type = *named++;
9559 data_type = *named++; /* type of data */
9560 if (data_type == MONO_TYPE_SZARRAY)
9561 data_type = *named++;
9562 if (data_type == MONO_TYPE_ENUM) {
9565 type_len = mono_metadata_decode_blob_size (named, &named);
9566 type_name = (char *)g_malloc (type_len + 1);
9567 memcpy (type_name, named, type_len);
9568 type_name [type_len] = 0;
9570 /* FIXME: lookup the type and check type consistency */
9573 name_len = mono_metadata_decode_blob_size (named, &named);
9574 name = (char *)g_malloc (name_len + 1);
9575 memcpy (name, named, name_len);
9576 name [name_len] = 0;
9578 if (named_type == 0x53) {
9579 MonoClassField *field;
9582 /* how this fail is a blackbox */
9583 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9585 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9590 val = load_cattr_value (image, field->type, named, &named, error);
9591 if (!mono_error_ok (error)) {
9593 if (!type_is_reference (field->type))
9598 mono_field_set_value (attr, field, val);
9599 if (!type_is_reference (field->type))
9601 } else if (named_type == 0x54) {
9604 MonoType *prop_type;
9606 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9609 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9615 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9620 /* can we have more that 1 arg in a custom attr named property? */
9621 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9622 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9624 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9625 if (!mono_error_ok (error)) {
9627 if (!type_is_reference (prop_type))
9628 g_free (pparams [0]);
9633 mono_property_set_value_checked (prop, attr, pparams, error);
9634 if (!type_is_reference (prop_type))
9635 g_free (pparams [0]);
9636 if (!is_ok (error)) {
9644 free_param_data (method->signature, params);
9645 if (params != params_buf)
9646 mono_gc_free_fixed (params);
9651 free_param_data (method->signature, params);
9652 if (params != params_buf)
9653 mono_gc_free_fixed (params);
9658 * mono_reflection_create_custom_attr_data_args:
9660 * Create an array of typed and named arguments from the cattr blob given by DATA.
9661 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9662 * NAMED_ARG_INFO will contain information about the named arguments.
9665 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)
9667 MonoArray *typedargs, *namedargs;
9668 MonoClass *attrklass;
9670 const char *p = (const char*)data;
9672 guint32 i, j, num_named;
9673 CattrNamedArg *arginfo = NULL;
9677 *named_arg_info = NULL;
9679 mono_error_init (error);
9681 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9682 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9686 mono_class_init (method->klass);
9688 domain = mono_domain_get ();
9690 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9693 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9694 return_if_nok (error);
9698 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9701 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9702 return_if_nok (error);
9703 mono_array_setref (typedargs, i, obj);
9707 num_named = read16 (named);
9708 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9709 return_if_nok (error);
9711 attrklass = method->klass;
9713 arginfo = g_new0 (CattrNamedArg, num_named);
9714 *named_arg_info = arginfo;
9716 for (j = 0; j < num_named; j++) {
9718 char *name, named_type, data_type;
9719 named_type = *named++;
9720 data_type = *named++; /* type of data */
9721 if (data_type == MONO_TYPE_SZARRAY)
9722 data_type = *named++;
9723 if (data_type == MONO_TYPE_ENUM) {
9726 type_len = mono_metadata_decode_blob_size (named, &named);
9727 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9730 type_name = (char *)g_malloc (type_len + 1);
9731 memcpy (type_name, named, type_len);
9732 type_name [type_len] = 0;
9734 /* FIXME: lookup the type and check type consistency */
9737 name_len = mono_metadata_decode_blob_size (named, &named);
9738 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9740 name = (char *)g_malloc (name_len + 1);
9741 memcpy (name, named, name_len);
9742 name [name_len] = 0;
9744 if (named_type == 0x53) {
9746 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9753 arginfo [j].type = field->type;
9754 arginfo [j].field = field;
9756 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9757 if (!is_ok (error)) {
9761 mono_array_setref (namedargs, j, obj);
9763 } else if (named_type == 0x54) {
9765 MonoType *prop_type;
9766 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9768 if (!prop || !prop->set) {
9773 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9774 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9776 arginfo [j].type = prop_type;
9777 arginfo [j].prop = prop;
9779 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9780 if (!is_ok (error)) {
9784 mono_array_setref (namedargs, j, obj);
9789 *typed_args = typedargs;
9790 *named_args = namedargs;
9793 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9795 *named_arg_info = NULL;
9799 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9802 MonoArray *typedargs, *namedargs;
9805 CattrNamedArg *arginfo = NULL;
9808 mono_error_init (error);
9816 image = assembly->assembly->image;
9817 method = ref_method->method;
9818 domain = mono_object_domain (ref_method);
9820 if (!mono_class_init (method->klass)) {
9821 mono_error_set_for_class_failure (error, method->klass);
9825 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9829 if (!typedargs || !namedargs)
9832 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9833 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9834 MonoObject *typedarg;
9836 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9839 mono_array_setref (typedargs, i, typedarg);
9842 for (i = 0; i < mono_array_length (namedargs); ++i) {
9843 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9844 MonoObject *typedarg, *namedarg, *minfo;
9846 if (arginfo [i].prop) {
9847 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9851 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9856 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9859 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9863 mono_array_setref (namedargs, i, namedarg);
9866 *ctor_args = typedargs;
9867 *named_args = namedargs;
9871 return mono_error_ok (error);
9875 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9878 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9879 mono_error_set_pending_exception (&error);
9883 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9885 static MonoMethod *ctor;
9891 mono_error_init (error);
9893 g_assert (image->assembly);
9896 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9898 domain = mono_domain_get ();
9899 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9900 return_val_if_nok (error, NULL);
9901 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9902 return_val_if_nok (error, NULL);
9903 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9904 return_val_if_nok (error, NULL);
9905 params [2] = (gpointer)&cattr->data;
9906 params [3] = &cattr->data_size;
9908 mono_runtime_invoke_checked (ctor, attr, params, error);
9909 return_val_if_nok (error, NULL);
9914 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9920 mono_error_init (error);
9923 for (i = 0; i < cinfo->num_attrs; ++i) {
9924 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9928 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9929 return_val_if_nok (error, NULL);
9931 for (i = 0; i < cinfo->num_attrs; ++i) {
9932 if (!cinfo->attrs [i].ctor) {
9933 /* The cattr type is not finished yet */
9934 /* We should include the type name but cinfo doesn't contain it */
9935 mono_error_set_type_load_name (error, NULL, NULL, "");
9938 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9939 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9940 if (!mono_error_ok (error))
9942 mono_array_setref (result, n, attr);
9950 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9953 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9954 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9960 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9966 mono_error_init (error);
9967 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9968 return_val_if_nok (error, NULL);
9969 for (i = 0; i < cinfo->num_attrs; ++i) {
9970 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9971 return_val_if_nok (error, NULL);
9972 mono_array_setref (result, i, attr);
9978 * mono_custom_attrs_from_index:
9980 * Returns: NULL if no attributes are found or if a loading error occurs.
9983 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9986 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9987 mono_error_cleanup (&error);
9991 * mono_custom_attrs_from_index_checked:
9993 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9996 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9998 guint32 mtoken, i, len;
9999 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
10001 MonoCustomAttrInfo *ainfo;
10002 GList *tmp, *list = NULL;
10004 MonoCustomAttrEntry* attr;
10006 mono_error_init (error);
10008 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
10010 i = mono_metadata_custom_attrs_from_index (image, idx);
10014 while (i < ca->rows) {
10015 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
10017 list = g_list_prepend (list, GUINT_TO_POINTER (i));
10020 len = g_list_length (list);
10023 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
10024 ainfo->num_attrs = len;
10025 ainfo->image = image;
10026 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
10027 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
10028 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
10029 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
10030 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
10031 mtoken |= MONO_TOKEN_METHOD_DEF;
10033 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
10034 mtoken |= MONO_TOKEN_MEMBER_REF;
10037 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
10040 attr = &ainfo->attrs [i - 1];
10041 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10043 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10044 g_list_free (list);
10049 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10050 /*FIXME raising an exception here doesn't make any sense*/
10051 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10052 g_list_free (list);
10056 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10057 attr->data_size = mono_metadata_decode_value (data, &data);
10058 attr->data = (guchar*)data;
10060 g_list_free (list);
10065 MonoCustomAttrInfo*
10066 mono_custom_attrs_from_method (MonoMethod *method)
10069 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
10070 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10074 MonoCustomAttrInfo*
10075 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10079 mono_error_init (error);
10082 * An instantiated method has the same cattrs as the generic method definition.
10084 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10085 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10087 if (method->is_inflated)
10088 method = ((MonoMethodInflated *) method)->declaring;
10090 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10091 return lookup_custom_attr (method->klass->image, method);
10093 if (!method->token)
10094 /* Synthetic methods */
10097 idx = mono_method_get_index (method);
10098 idx <<= MONO_CUSTOM_ATTR_BITS;
10099 idx |= MONO_CUSTOM_ATTR_METHODDEF;
10100 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10103 MonoCustomAttrInfo*
10104 mono_custom_attrs_from_class (MonoClass *klass)
10107 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10108 mono_error_cleanup (&error);
10112 MonoCustomAttrInfo*
10113 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10117 mono_error_init (error);
10119 if (klass->generic_class)
10120 klass = klass->generic_class->container_class;
10122 if (image_is_dynamic (klass->image))
10123 return lookup_custom_attr (klass->image, klass);
10125 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10126 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10127 idx <<= MONO_CUSTOM_ATTR_BITS;
10128 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10130 idx = mono_metadata_token_index (klass->type_token);
10131 idx <<= MONO_CUSTOM_ATTR_BITS;
10132 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10134 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10137 MonoCustomAttrInfo*
10138 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10141 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10142 mono_error_cleanup (&error);
10146 MonoCustomAttrInfo*
10147 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10151 mono_error_init (error);
10153 if (image_is_dynamic (assembly->image))
10154 return lookup_custom_attr (assembly->image, assembly);
10155 idx = 1; /* there is only one assembly */
10156 idx <<= MONO_CUSTOM_ATTR_BITS;
10157 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10158 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10161 static MonoCustomAttrInfo*
10162 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10166 if (image_is_dynamic (image))
10167 return lookup_custom_attr (image, image);
10168 idx = 1; /* there is only one module */
10169 idx <<= MONO_CUSTOM_ATTR_BITS;
10170 idx |= MONO_CUSTOM_ATTR_MODULE;
10171 return mono_custom_attrs_from_index_checked (image, idx, error);
10174 MonoCustomAttrInfo*
10175 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10178 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10179 mono_error_cleanup (&error);
10183 MonoCustomAttrInfo*
10184 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10188 if (image_is_dynamic (klass->image)) {
10189 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10190 return lookup_custom_attr (klass->image, property);
10192 idx = find_property_index (klass, property);
10193 idx <<= MONO_CUSTOM_ATTR_BITS;
10194 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10195 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10198 MonoCustomAttrInfo*
10199 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10202 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10203 mono_error_cleanup (&error);
10207 MonoCustomAttrInfo*
10208 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10212 if (image_is_dynamic (klass->image)) {
10213 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10214 return lookup_custom_attr (klass->image, event);
10216 idx = find_event_index (klass, event);
10217 idx <<= MONO_CUSTOM_ATTR_BITS;
10218 idx |= MONO_CUSTOM_ATTR_EVENT;
10219 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10222 MonoCustomAttrInfo*
10223 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10226 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10227 mono_error_cleanup (&error);
10231 MonoCustomAttrInfo*
10232 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10235 mono_error_init (error);
10237 if (image_is_dynamic (klass->image)) {
10238 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10239 return lookup_custom_attr (klass->image, field);
10241 idx = find_field_index (klass, field);
10242 idx <<= MONO_CUSTOM_ATTR_BITS;
10243 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10244 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10248 * mono_custom_attrs_from_param:
10249 * @method: handle to the method that we want to retrieve custom parameter information from
10250 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10252 * The result must be released with mono_custom_attrs_free().
10254 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10256 MonoCustomAttrInfo*
10257 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10260 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10261 mono_error_cleanup (&error);
10266 * mono_custom_attrs_from_param_checked:
10267 * @method: handle to the method that we want to retrieve custom parameter information from
10268 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10269 * @error: set on error
10271 * The result must be released with mono_custom_attrs_free().
10273 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10275 MonoCustomAttrInfo*
10276 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10279 guint32 i, idx, method_index;
10280 guint32 param_list, param_last, param_pos, found;
10282 MonoReflectionMethodAux *aux;
10284 mono_error_init (error);
10287 * An instantiated method has the same cattrs as the generic method definition.
10289 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10290 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10292 if (method->is_inflated)
10293 method = ((MonoMethodInflated *) method)->declaring;
10295 if (image_is_dynamic (method->klass->image)) {
10296 MonoCustomAttrInfo *res, *ainfo;
10299 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10300 if (!aux || !aux->param_cattr)
10303 /* Need to copy since it will be freed later */
10304 ainfo = aux->param_cattr [param];
10307 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10308 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10309 memcpy (res, ainfo, size);
10313 image = method->klass->image;
10314 method_index = mono_method_get_index (method);
10317 ca = &image->tables [MONO_TABLE_METHOD];
10319 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10320 if (method_index == ca->rows) {
10321 ca = &image->tables [MONO_TABLE_PARAM];
10322 param_last = ca->rows + 1;
10324 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10325 ca = &image->tables [MONO_TABLE_PARAM];
10328 for (i = param_list; i < param_last; ++i) {
10329 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10330 if (param_pos == param) {
10338 idx <<= MONO_CUSTOM_ATTR_BITS;
10339 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10340 return mono_custom_attrs_from_index_checked (image, idx, error);
10344 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10348 for (i = 0; i < ainfo->num_attrs; ++i) {
10349 klass = ainfo->attrs [i].ctor->klass;
10350 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10357 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10360 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10361 mono_error_assert_ok (&error); /*FIXME proper error handling*/
10366 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10372 mono_error_init (error);
10375 for (i = 0; i < ainfo->num_attrs; ++i) {
10376 klass = ainfo->attrs [i].ctor->klass;
10377 if (mono_class_has_parent (klass, attr_klass)) {
10382 if (attr_index == -1)
10385 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10386 if (!mono_error_ok (error))
10388 return mono_array_get (attrs, MonoObject*, attr_index);
10392 * mono_reflection_get_custom_attrs_info:
10393 * @obj: a reflection object handle
10395 * Return the custom attribute info for attributes defined for the
10396 * reflection handle @obj. The objects.
10398 * FIXME this function leaks like a sieve for SRE objects.
10400 MonoCustomAttrInfo*
10401 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10404 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10405 mono_error_assert_ok (&error);
10410 * mono_reflection_get_custom_attrs_info_checked:
10411 * @obj: a reflection object handle
10412 * @error: set on error
10414 * Return the custom attribute info for attributes defined for the
10415 * reflection handle @obj. The objects.
10417 * On failure returns NULL and sets @error.
10419 * FIXME this function leaks like a sieve for SRE objects.
10421 MonoCustomAttrInfo*
10422 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10425 MonoCustomAttrInfo *cinfo = NULL;
10427 mono_error_init (error);
10429 klass = obj->vtable->klass;
10430 if (klass == mono_defaults.runtimetype_class) {
10431 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10432 return_val_if_nok (error, NULL);
10433 klass = mono_class_from_mono_type (type);
10434 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10435 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10436 return_val_if_nok (error, NULL);
10437 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10438 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10439 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10440 return_val_if_nok (error, NULL);
10441 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10442 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10443 cinfo = mono_custom_attrs_from_module (module->image, error);
10444 return_val_if_nok (error, NULL);
10445 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10446 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10447 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10448 return_val_if_nok (error, NULL);
10449 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10450 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10451 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10452 return_val_if_nok (error, NULL);
10453 } else if (strcmp ("MonoField", klass->name) == 0) {
10454 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10455 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10456 return_val_if_nok (error, NULL);
10457 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10458 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10459 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10460 return_val_if_nok (error, NULL);
10461 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10462 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10463 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10464 return_val_if_nok (error, NULL);
10465 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10466 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10467 MonoClass *member_class = mono_object_class (param->MemberImpl);
10468 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10469 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10470 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10471 return_val_if_nok (error, NULL);
10472 } else if (is_sr_mono_property (member_class)) {
10473 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10474 MonoMethod *method;
10475 if (!(method = prop->property->get))
10476 method = prop->property->set;
10479 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10480 return_val_if_nok (error, NULL);
10482 #ifndef DISABLE_REFLECTION_EMIT
10483 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10484 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10485 return_val_if_nok (error, NULL);
10486 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10487 return_val_if_nok (error, NULL);
10488 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10489 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10490 MonoMethod *method = NULL;
10491 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10492 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10493 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10494 method = ((MonoReflectionMethod *)c->cb)->method;
10496 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));
10498 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10499 return_val_if_nok (error, NULL);
10503 char *type_name = mono_type_get_full_name (member_class);
10504 mono_error_set_not_supported (error,
10505 "Custom attributes on a ParamInfo with member %s are not supported",
10507 g_free (type_name);
10510 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10511 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10512 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10513 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10515 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10516 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10517 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10518 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10519 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10520 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10521 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10522 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10523 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10524 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10525 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10526 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10527 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10528 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10529 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10530 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10531 return_val_if_nok (error, NULL);
10532 } else { /* handle other types here... */
10533 g_error ("get custom attrs not yet supported for %s", klass->name);
10540 * mono_reflection_get_custom_attrs_by_type:
10541 * @obj: a reflection object handle
10543 * Return an array with all the custom attributes defined of the
10544 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10545 * of that type are returned. The objects are fully build. Return NULL if a loading error
10549 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10552 MonoCustomAttrInfo *cinfo;
10554 mono_error_init (error);
10556 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10557 return_val_if_nok (error, NULL);
10559 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10560 if (!cinfo->cached)
10561 mono_custom_attrs_free (cinfo);
10565 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10572 * mono_reflection_get_custom_attrs:
10573 * @obj: a reflection object handle
10575 * Return an array with all the custom attributes defined of the
10576 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10580 mono_reflection_get_custom_attrs (MonoObject *obj)
10584 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10588 * mono_reflection_get_custom_attrs_data:
10589 * @obj: a reflection obj handle
10591 * Returns an array of System.Reflection.CustomAttributeData,
10592 * which include information about attributes reflected on
10593 * types loaded using the Reflection Only methods
10596 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10600 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10601 mono_error_cleanup (&error);
10606 * mono_reflection_get_custom_attrs_data_checked:
10607 * @obj: a reflection obj handle
10608 * @error: set on error
10610 * Returns an array of System.Reflection.CustomAttributeData,
10611 * which include information about attributes reflected on
10612 * types loaded using the Reflection Only methods
10615 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10618 MonoCustomAttrInfo *cinfo;
10620 mono_error_init (error);
10622 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10623 return_val_if_nok (error, NULL);
10625 result = mono_custom_attrs_data_construct (cinfo, error);
10626 if (!cinfo->cached)
10627 mono_custom_attrs_free (cinfo);
10628 return_val_if_nok (error, NULL);
10630 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10635 static MonoReflectionType*
10636 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10638 static MonoMethod *method_get_underlying_system_type = NULL;
10639 MonoReflectionType *rt;
10640 MonoMethod *usertype_method;
10642 mono_error_init (error);
10644 if (!method_get_underlying_system_type)
10645 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10647 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10649 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10656 is_corlib_type (MonoClass *klass)
10658 return klass->image == mono_defaults.corlib;
10661 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10662 static MonoClass *cached_class; \
10663 if (cached_class) \
10664 return cached_class == _class; \
10665 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10666 cached_class = _class; \
10673 #ifndef DISABLE_REFLECTION_EMIT
10675 is_sre_array (MonoClass *klass)
10677 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10681 is_sre_byref (MonoClass *klass)
10683 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10687 is_sre_pointer (MonoClass *klass)
10689 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10693 is_sre_generic_instance (MonoClass *klass)
10695 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10699 is_sre_type_builder (MonoClass *klass)
10701 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10705 is_sre_method_builder (MonoClass *klass)
10707 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10711 is_sre_ctor_builder (MonoClass *klass)
10713 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10717 is_sre_field_builder (MonoClass *klass)
10719 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10723 is_sre_method_on_tb_inst (MonoClass *klass)
10725 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10729 is_sre_ctor_on_tb_inst (MonoClass *klass)
10731 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10735 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10738 mono_error_init (error);
10745 if (is_usertype (ref)) {
10746 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10747 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10753 klass = mono_object_class (ref);
10755 if (is_sre_array (klass)) {
10757 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10758 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10759 return_val_if_nok (error, NULL);
10761 if (sre_array->rank == 0) //single dimentional array
10762 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10764 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10765 sre_array->type.type = res;
10767 } else if (is_sre_byref (klass)) {
10769 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10770 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10771 return_val_if_nok (error, NULL);
10773 res = &mono_class_from_mono_type (base)->this_arg;
10774 sre_byref->type.type = res;
10776 } else if (is_sre_pointer (klass)) {
10778 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10779 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10780 return_val_if_nok (error, NULL);
10782 res = &mono_ptr_class_get (base)->byval_arg;
10783 sre_pointer->type.type = res;
10785 } else if (is_sre_generic_instance (klass)) {
10786 MonoType *res, **types;
10787 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10790 count = mono_array_length (gclass->type_arguments);
10791 types = g_new0 (MonoType*, count);
10792 for (i = 0; i < count; ++i) {
10793 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10794 types [i] = mono_reflection_type_get_handle (t, error);
10795 if (!types[i] || !is_ok (error)) {
10801 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10804 gclass->type.type = res;
10808 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10813 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10816 mono_reflection_type_get_handle (type, &error);
10817 mono_error_set_pending_exception (&error);
10821 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10823 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10826 mono_error_init (error);
10828 MonoType *res = mono_reflection_type_get_handle (type, error);
10830 if (!res && is_ok (error)) {
10831 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10833 return_val_if_nok (error, FALSE);
10835 klass = mono_class_from_mono_type (res);
10837 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10838 mono_domain_lock (domain);
10840 if (!image_is_dynamic (klass->image)) {
10841 mono_class_setup_supertypes (klass);
10843 if (!domain->type_hash)
10844 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10845 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10846 mono_g_hash_table_insert (domain->type_hash, res, type);
10848 mono_domain_unlock (domain);
10849 mono_loader_unlock ();
10855 mono_reflection_register_with_runtime (MonoReflectionType *type)
10858 (void) reflection_register_with_runtime (type, &error);
10859 mono_error_set_pending_exception (&error);
10863 * LOCKING: Assumes the loader lock is held.
10865 static MonoMethodSignature*
10866 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10867 MonoMethodSignature *sig;
10870 mono_error_init (error);
10872 count = parameters? mono_array_length (parameters): 0;
10874 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10875 sig->param_count = count;
10876 sig->sentinelpos = -1; /* FIXME */
10877 for (i = 0; i < count; ++i) {
10878 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10879 if (!is_ok (error)) {
10880 image_g_free (image, sig);
10888 * LOCKING: Assumes the loader lock is held.
10890 static MonoMethodSignature*
10891 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10892 MonoMethodSignature *sig;
10894 mono_error_init (error);
10896 sig = parameters_to_signature (image, ctor->parameters, error);
10897 return_val_if_nok (error, NULL);
10898 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10899 sig->ret = &mono_defaults.void_class->byval_arg;
10904 * LOCKING: Assumes the loader lock is held.
10906 static MonoMethodSignature*
10907 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10908 MonoMethodSignature *sig;
10910 mono_error_init (error);
10912 sig = parameters_to_signature (image, method->parameters, error);
10913 return_val_if_nok (error, NULL);
10914 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10915 if (method->rtype) {
10916 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10917 if (!is_ok (error)) {
10918 image_g_free (image, sig);
10922 sig->ret = &mono_defaults.void_class->byval_arg;
10924 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10928 static MonoMethodSignature*
10929 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10930 MonoMethodSignature *sig;
10932 mono_error_init (error);
10934 sig = parameters_to_signature (NULL, method->parameters, error);
10935 return_val_if_nok (error, NULL);
10936 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10937 if (method->rtype) {
10938 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10939 if (!is_ok (error)) {
10944 sig->ret = &mono_defaults.void_class->byval_arg;
10946 sig->generic_param_count = 0;
10951 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10953 mono_error_init (error);
10954 MonoClass *klass = mono_object_class (prop);
10955 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10956 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10957 *name = mono_string_to_utf8_checked (pb->name, error);
10958 return_if_nok (error);
10959 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10961 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10962 *name = g_strdup (p->property->name);
10963 if (p->property->get)
10964 *type = mono_method_signature (p->property->get)->ret;
10966 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10971 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10973 mono_error_init (error);
10974 MonoClass *klass = mono_object_class (field);
10975 if (strcmp (klass->name, "FieldBuilder") == 0) {
10976 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10977 *name = mono_string_to_utf8_checked (fb->name, error);
10978 return_if_nok (error);
10979 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10981 MonoReflectionField *f = (MonoReflectionField *)field;
10982 *name = g_strdup (mono_field_get_name (f->field));
10983 *type = f->field->type;
10987 #else /* DISABLE_REFLECTION_EMIT */
10990 mono_reflection_register_with_runtime (MonoReflectionType *type)
10992 /* This is empty */
10996 is_sre_type_builder (MonoClass *klass)
11002 is_sre_generic_instance (MonoClass *klass)
11008 init_type_builder_generics (MonoObject *type, MonoError *error)
11010 mono_error_init (error);
11013 #endif /* !DISABLE_REFLECTION_EMIT */
11017 is_sr_mono_field (MonoClass *klass)
11019 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
11023 is_sr_mono_property (MonoClass *klass)
11025 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
11029 is_sr_mono_method (MonoClass *klass)
11031 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
11035 is_sr_mono_cmethod (MonoClass *klass)
11037 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
11041 is_sr_mono_generic_method (MonoClass *klass)
11043 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11047 is_sr_mono_generic_cmethod (MonoClass *klass)
11049 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11053 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11055 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11059 is_usertype (MonoReflectionType *ref)
11061 MonoClass *klass = mono_object_class (ref);
11062 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11065 static MonoReflectionType*
11066 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11068 mono_error_init (error);
11069 if (!type || type->type)
11072 if (is_usertype (type)) {
11073 type = mono_reflection_type_get_underlying_system_type (type, error);
11074 return_val_if_nok (error, NULL);
11075 if (is_usertype (type)) {
11076 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11084 * encode_cattr_value:
11085 * Encode a value in a custom attribute stream of bytes.
11086 * The value to encode is either supplied as an object in argument val
11087 * (valuetypes are boxed), or as a pointer to the data in the
11089 * @type represents the type of the value
11090 * @buffer is the start of the buffer
11091 * @p the current position in the buffer
11092 * @buflen contains the size of the buffer and is used to return the new buffer size
11093 * if this needs to be realloced.
11094 * @retbuffer and @retp return the start and the position of the buffer
11095 * @error set on error.
11098 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11100 MonoTypeEnum simple_type;
11102 mono_error_init (error);
11103 if ((p-buffer) + 10 >= *buflen) {
11106 newbuf = (char *)g_realloc (buffer, *buflen);
11107 p = newbuf + (p-buffer);
11111 argval = ((char*)arg + sizeof (MonoObject));
11112 simple_type = type->type;
11114 switch (simple_type) {
11115 case MONO_TYPE_BOOLEAN:
11120 case MONO_TYPE_CHAR:
11123 swap_with_size (p, argval, 2, 1);
11129 swap_with_size (p, argval, 4, 1);
11133 swap_with_size (p, argval, 8, 1);
11138 swap_with_size (p, argval, 8, 1);
11141 case MONO_TYPE_VALUETYPE:
11142 if (type->data.klass->enumtype) {
11143 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11146 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11149 case MONO_TYPE_STRING: {
11156 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11157 return_if_nok (error);
11158 slen = strlen (str);
11159 if ((p-buffer) + 10 + slen >= *buflen) {
11163 newbuf = (char *)g_realloc (buffer, *buflen);
11164 p = newbuf + (p-buffer);
11167 mono_metadata_encode_value (slen, p, &p);
11168 memcpy (p, str, slen);
11173 case MONO_TYPE_CLASS: {
11176 MonoType *arg_type;
11182 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11183 return_if_nok (error);
11185 str = type_get_qualified_name (arg_type, NULL);
11186 slen = strlen (str);
11187 if ((p-buffer) + 10 + slen >= *buflen) {
11191 newbuf = (char *)g_realloc (buffer, *buflen);
11192 p = newbuf + (p-buffer);
11195 mono_metadata_encode_value (slen, p, &p);
11196 memcpy (p, str, slen);
11201 case MONO_TYPE_SZARRAY: {
11203 MonoClass *eclass, *arg_eclass;
11206 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11209 len = mono_array_length ((MonoArray*)arg);
11211 *p++ = (len >> 8) & 0xff;
11212 *p++ = (len >> 16) & 0xff;
11213 *p++ = (len >> 24) & 0xff;
11215 *retbuffer = buffer;
11216 eclass = type->data.klass;
11217 arg_eclass = mono_object_class (arg)->element_class;
11220 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11221 eclass = mono_defaults.object_class;
11223 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11224 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11225 int elsize = mono_class_array_element_size (arg_eclass);
11226 for (i = 0; i < len; ++i) {
11227 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11228 return_if_nok (error);
11231 } else if (eclass->valuetype && arg_eclass->valuetype) {
11232 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11233 int elsize = mono_class_array_element_size (eclass);
11234 for (i = 0; i < len; ++i) {
11235 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11236 return_if_nok (error);
11240 for (i = 0; i < len; ++i) {
11241 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11242 return_if_nok (error);
11247 case MONO_TYPE_OBJECT: {
11253 * The parameter type is 'object' but the type of the actual
11254 * argument is not. So we have to add type information to the blob
11255 * too. This is completely undocumented in the spec.
11259 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11264 klass = mono_object_class (arg);
11266 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11270 return_if_nok (error);
11273 if (klass->enumtype) {
11275 } else if (klass == mono_defaults.string_class) {
11276 simple_type = MONO_TYPE_STRING;
11279 } else if (klass->rank == 1) {
11281 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11282 /* See Partition II, Appendix B3 */
11285 *p++ = klass->element_class->byval_arg.type;
11286 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11287 return_if_nok (error);
11289 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11290 *p++ = simple_type = klass->byval_arg.type;
11293 g_error ("unhandled type in custom attr");
11295 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11296 slen = strlen (str);
11297 if ((p-buffer) + 10 + slen >= *buflen) {
11301 newbuf = (char *)g_realloc (buffer, *buflen);
11302 p = newbuf + (p-buffer);
11305 mono_metadata_encode_value (slen, p, &p);
11306 memcpy (p, str, slen);
11309 simple_type = mono_class_enum_basetype (klass)->type;
11313 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11316 *retbuffer = buffer;
11320 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11322 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11323 char *str = type_get_qualified_name (type, NULL);
11324 int slen = strlen (str);
11328 * This seems to be optional...
11331 mono_metadata_encode_value (slen, p, &p);
11332 memcpy (p, str, slen);
11335 } else if (type->type == MONO_TYPE_OBJECT) {
11337 } else if (type->type == MONO_TYPE_CLASS) {
11338 /* it should be a type: encode_cattr_value () has the check */
11341 mono_metadata_encode_value (type->type, p, &p);
11342 if (type->type == MONO_TYPE_SZARRAY)
11343 /* See the examples in Partition VI, Annex B */
11344 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11350 #ifndef DISABLE_REFLECTION_EMIT
11352 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11356 mono_error_init (error);
11358 /* Preallocate a large enough buffer */
11359 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11360 char *str = type_get_qualified_name (type, NULL);
11361 len = strlen (str);
11363 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11364 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11365 len = strlen (str);
11370 len += strlen (name);
11372 if ((p-buffer) + 20 + len >= *buflen) {
11376 newbuf = (char *)g_realloc (buffer, *buflen);
11377 p = newbuf + (p-buffer);
11381 encode_field_or_prop_type (type, p, &p);
11383 len = strlen (name);
11384 mono_metadata_encode_value (len, p, &p);
11385 memcpy (p, name, len);
11387 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11388 return_if_nok (error);
11390 *retbuffer = buffer;
11394 * mono_reflection_get_custom_attrs_blob:
11395 * @ctor: custom attribute constructor
11396 * @ctorArgs: arguments o the constructor
11402 * Creates the blob of data that needs to be saved in the metadata and that represents
11403 * the custom attributed described by @ctor, @ctorArgs etc.
11404 * Returns: a Byte array representing the blob of data.
11407 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11410 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11411 mono_error_cleanup (&error);
11416 * mono_reflection_get_custom_attrs_blob_checked:
11417 * @ctor: custom attribute constructor
11418 * @ctorArgs: arguments o the constructor
11423 * @error: set on error
11425 * Creates the blob of data that needs to be saved in the metadata and that represents
11426 * the custom attributed described by @ctor, @ctorArgs etc.
11427 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11430 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11432 MonoArray *result = NULL;
11433 MonoMethodSignature *sig;
11438 mono_error_init (error);
11440 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11441 /* sig is freed later so allocate it in the heap */
11442 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11443 if (!is_ok (error)) {
11448 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11451 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11453 p = buffer = (char *)g_malloc (buflen);
11454 /* write the prolog */
11457 for (i = 0; i < sig->param_count; ++i) {
11458 arg = mono_array_get (ctorArgs, MonoObject*, i);
11459 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11460 if (!is_ok (error)) goto leave;
11464 i += mono_array_length (properties);
11466 i += mono_array_length (fields);
11468 *p++ = (i >> 8) & 0xff;
11471 for (i = 0; i < mono_array_length (properties); ++i) {
11475 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11476 get_prop_name_and_type (prop, &pname, &ptype, error);
11477 if (!is_ok (error)) goto leave;
11478 *p++ = 0x54; /* PROPERTY signature */
11479 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11481 if (!is_ok (error)) goto leave;
11487 for (i = 0; i < mono_array_length (fields); ++i) {
11491 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11492 get_field_name_and_type (field, &fname, &ftype, error);
11493 if (!is_ok (error)) goto leave;
11494 *p++ = 0x53; /* FIELD signature */
11495 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11497 if (!is_ok (error)) goto leave;
11501 g_assert (p - buffer <= buflen);
11502 buflen = p - buffer;
11503 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11504 if (!is_ok (error))
11506 p = mono_array_addr (result, char, 0);
11507 memcpy (p, buffer, buflen);
11510 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11516 * reflection_setup_internal_class:
11517 * @tb: a TypeBuilder object
11518 * @error: set on error
11520 * Creates a MonoClass that represents the TypeBuilder.
11521 * This is a trick that lets us simplify a lot of reflection code
11522 * (and will allow us to support Build and Run assemblies easier).
11524 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11527 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11529 MonoClass *klass, *parent;
11531 mono_error_init (error);
11532 RESOLVE_TYPE (tb->parent, error);
11533 return_val_if_nok (error, FALSE);
11535 mono_loader_lock ();
11538 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11539 if (!is_ok (error)) {
11540 mono_loader_unlock ();
11543 /* check so we can compile corlib correctly */
11544 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11545 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11546 parent = parent_type->data.klass;
11548 parent = mono_class_from_mono_type (parent_type);
11554 /* the type has already being created: it means we just have to change the parent */
11555 if (tb->type.type) {
11556 klass = mono_class_from_mono_type (tb->type.type);
11557 klass->parent = NULL;
11558 /* fool mono_class_setup_parent */
11559 klass->supertypes = NULL;
11560 mono_class_setup_parent (klass, parent);
11561 mono_class_setup_mono_type (klass);
11562 mono_loader_unlock ();
11566 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11568 klass->image = &tb->module->dynamic_image->image;
11570 klass->inited = 1; /* we lie to the runtime */
11571 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11572 if (!is_ok (error))
11574 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11575 if (!is_ok (error))
11577 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11578 klass->flags = tb->attrs;
11580 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11582 klass->element_class = klass;
11584 if (mono_class_get_ref_info (klass) == NULL) {
11586 mono_class_set_ref_info (klass, tb);
11588 /* Put into cache so mono_class_get_checked () will find it.
11589 Skip nested types as those should not be available on the global scope. */
11590 if (!tb->nesting_type)
11591 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11594 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11595 by performing a mono_class_get which does the full resolution.
11597 Working around this semantics would require us to write a lot of code for no clear advantage.
11599 mono_image_append_class_to_reflection_info_set (klass);
11601 g_assert (mono_class_get_ref_info (klass) == tb);
11604 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11606 if (parent != NULL) {
11607 mono_class_setup_parent (klass, parent);
11608 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11609 const char *old_n = klass->name;
11610 /* trick to get relative numbering right when compiling corlib */
11611 klass->name = "BuildingObject";
11612 mono_class_setup_parent (klass, mono_defaults.object_class);
11613 klass->name = old_n;
11616 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11617 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11618 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11619 klass->instance_size = sizeof (MonoObject);
11620 klass->size_inited = 1;
11621 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11624 mono_class_setup_mono_type (klass);
11626 mono_class_setup_supertypes (klass);
11629 * FIXME: handle interfaces.
11632 tb->type.type = &klass->byval_arg;
11634 if (tb->nesting_type) {
11635 g_assert (tb->nesting_type->type);
11636 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11637 if (!is_ok (error)) goto failure;
11638 klass->nested_in = mono_class_from_mono_type (nesting_type);
11641 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11643 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11645 mono_loader_unlock ();
11649 mono_loader_unlock ();
11654 * mono_reflection_setup_internal_class:
11655 * @tb: a TypeBuilder object
11658 * Creates a MonoClass that represents the TypeBuilder.
11659 * This is a trick that lets us simplify a lot of reflection code
11660 * (and will allow us to support Build and Run assemblies easier).
11664 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11667 (void) reflection_setup_internal_class (tb, &error);
11668 mono_error_set_pending_exception (&error);
11672 * mono_reflection_setup_generic_class:
11673 * @tb: a TypeBuilder object
11675 * Setup the generic class before adding the first generic parameter.
11678 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11683 * mono_reflection_create_generic_class:
11684 * @tb: a TypeBuilder object
11685 * @error: set on error
11687 * Creates the generic class after all generic parameters have been added.
11688 * On success returns TRUE, on failure returns FALSE and sets @error.
11692 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11698 mono_error_init (error);
11700 klass = mono_class_from_mono_type (tb->type.type);
11702 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11704 if (klass->generic_container || (count == 0))
11707 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11709 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11711 klass->generic_container->owner.klass = klass;
11712 klass->generic_container->type_argc = count;
11713 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11715 klass->is_generic = 1;
11717 for (i = 0; i < count; i++) {
11718 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11719 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11720 return_val_if_nok (error, FALSE);
11721 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11722 klass->generic_container->type_params [i] = *param;
11723 /*Make sure we are a diferent type instance */
11724 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11725 klass->generic_container->type_params [i].info.pklass = NULL;
11726 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11728 g_assert (klass->generic_container->type_params [i].param.owner);
11731 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11736 * reflection_create_internal_class:
11737 * @tb: a TypeBuilder object
11738 * @error: set on error
11740 * Actually create the MonoClass that is associated with the TypeBuilder.
11741 * On success returns TRUE, on failure returns FALSE and sets @error.
11745 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11750 mono_error_init (error);
11751 klass = mono_class_from_mono_type (tb->type.type);
11753 mono_loader_lock ();
11754 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11755 MonoReflectionFieldBuilder *fb;
11757 MonoType *enum_basetype;
11759 g_assert (tb->fields != NULL);
11760 g_assert (mono_array_length (tb->fields) >= 1);
11762 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11764 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11765 if (!is_ok (error)) {
11766 mono_loader_unlock ();
11769 if (!mono_type_is_valid_enum_basetype (field_type)) {
11770 mono_loader_unlock ();
11774 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11775 if (!is_ok (error)) {
11776 mono_loader_unlock ();
11779 klass->element_class = mono_class_from_mono_type (enum_basetype);
11780 if (!klass->element_class)
11781 klass->element_class = mono_class_from_mono_type (enum_basetype);
11784 * get the element_class from the current corlib.
11786 ec = default_class_from_mono_type (enum_basetype);
11787 klass->instance_size = ec->instance_size;
11788 klass->size_inited = 1;
11790 * this is almost safe to do with enums and it's needed to be able
11791 * to create objects of the enum type (for use in SetConstant).
11793 /* FIXME: Does this mean enums can't have method overrides ? */
11794 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11796 mono_loader_unlock ();
11801 * mono_reflection_create_internal_class:
11802 * @tb: a TypeBuilder object
11805 * Actually create the MonoClass that is associated with the TypeBuilder.
11808 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11811 (void) reflection_create_internal_class (tb, &error);
11812 mono_error_set_pending_exception (&error);
11815 static MonoMarshalSpec*
11816 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11817 MonoReflectionMarshal *minfo, MonoError *error)
11819 MonoMarshalSpec *res;
11821 mono_error_init (error);
11823 res = image_g_new0 (image, MonoMarshalSpec, 1);
11824 res->native = (MonoMarshalNative)minfo->type;
11826 switch (minfo->type) {
11827 case MONO_NATIVE_LPARRAY:
11828 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11829 if (minfo->has_size) {
11830 res->data.array_data.param_num = minfo->param_num;
11831 res->data.array_data.num_elem = minfo->count;
11832 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11835 res->data.array_data.param_num = -1;
11836 res->data.array_data.num_elem = -1;
11837 res->data.array_data.elem_mult = -1;
11841 case MONO_NATIVE_BYVALTSTR:
11842 case MONO_NATIVE_BYVALARRAY:
11843 res->data.array_data.num_elem = minfo->count;
11846 case MONO_NATIVE_CUSTOM:
11847 if (minfo->marshaltyperef) {
11848 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11849 if (!is_ok (error)) {
11850 image_g_free (image, res);
11853 res->data.custom_data.custom_name =
11854 type_get_fully_qualified_name (marshaltyperef);
11856 if (minfo->mcookie) {
11857 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11858 if (!is_ok (error)) {
11859 image_g_free (image, res);
11871 #endif /* !DISABLE_REFLECTION_EMIT */
11873 MonoReflectionMarshalAsAttribute*
11874 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11875 MonoMarshalSpec *spec, MonoError *error)
11877 MonoReflectionType *rt;
11878 MonoReflectionMarshalAsAttribute *minfo;
11881 mono_error_init (error);
11883 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11886 minfo->utype = spec->native;
11888 switch (minfo->utype) {
11889 case MONO_NATIVE_LPARRAY:
11890 minfo->array_subtype = spec->data.array_data.elem_type;
11891 minfo->size_const = spec->data.array_data.num_elem;
11892 if (spec->data.array_data.param_num != -1)
11893 minfo->size_param_index = spec->data.array_data.param_num;
11896 case MONO_NATIVE_BYVALTSTR:
11897 case MONO_NATIVE_BYVALARRAY:
11898 minfo->size_const = spec->data.array_data.num_elem;
11901 case MONO_NATIVE_CUSTOM:
11902 if (spec->data.custom_data.custom_name) {
11903 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11904 return_val_if_nok (error, NULL);
11907 rt = mono_type_get_object_checked (domain, mtype, error);
11911 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11914 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11916 if (spec->data.custom_data.cookie)
11917 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11927 #ifndef DISABLE_REFLECTION_EMIT
11929 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11930 ReflectionMethodBuilder *rmb,
11931 MonoMethodSignature *sig,
11935 MonoMethodWrapper *wrapperm;
11936 MonoMarshalSpec **specs;
11937 MonoReflectionMethodAux *method_aux;
11942 mono_error_init (error);
11944 * Methods created using a MethodBuilder should have their memory allocated
11945 * inside the image mempool, while dynamic methods should have their memory
11948 dynamic = rmb->refs != NULL;
11949 image = dynamic ? NULL : klass->image;
11952 g_assert (!klass->generic_class);
11954 mono_loader_lock ();
11956 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11957 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11958 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11960 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11962 wrapperm = (MonoMethodWrapper*)m;
11964 m->dynamic = dynamic;
11966 m->flags = rmb->attrs;
11967 m->iflags = rmb->iattrs;
11968 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11970 m->signature = sig;
11971 m->sre_method = TRUE;
11972 m->skip_visibility = rmb->skip_visibility;
11973 if (rmb->table_idx)
11974 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11976 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11977 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11978 m->string_ctor = 1;
11980 m->signature->pinvoke = 1;
11981 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11982 m->signature->pinvoke = 1;
11984 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11986 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11987 mono_error_assert_ok (error);
11988 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11989 mono_error_assert_ok (error);
11991 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11993 if (image_is_dynamic (klass->image))
11994 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11996 mono_loader_unlock ();
11999 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
12000 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
12001 MonoMethodHeader *header;
12003 gint32 max_stack, i;
12004 gint32 num_locals = 0;
12005 gint32 num_clauses = 0;
12009 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
12010 code_size = rmb->ilgen->code_len;
12011 max_stack = rmb->ilgen->max_stack;
12012 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
12013 if (rmb->ilgen->ex_handlers)
12014 num_clauses = method_count_clauses (rmb->ilgen);
12017 code = mono_array_addr (rmb->code, guint8, 0);
12018 code_size = mono_array_length (rmb->code);
12019 /* we probably need to run a verifier on the code... */
12029 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
12030 header->code_size = code_size;
12031 header->code = (const unsigned char *)image_g_malloc (image, code_size);
12032 memcpy ((char*)header->code, code, code_size);
12033 header->max_stack = max_stack;
12034 header->init_locals = rmb->init_locals;
12035 header->num_locals = num_locals;
12037 for (i = 0; i < num_locals; ++i) {
12038 MonoReflectionLocalBuilder *lb =
12039 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
12041 header->locals [i] = image_g_new0 (image, MonoType, 1);
12042 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12043 mono_error_assert_ok (error);
12044 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12047 header->num_clauses = num_clauses;
12049 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12050 rmb->ilgen, num_clauses, error);
12051 mono_error_assert_ok (error);
12054 wrapperm->header = header;
12057 if (rmb->generic_params) {
12058 int count = mono_array_length (rmb->generic_params);
12059 MonoGenericContainer *container = rmb->generic_container;
12061 g_assert (container);
12063 container->type_argc = count;
12064 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12065 container->owner.method = m;
12066 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12068 m->is_generic = TRUE;
12069 mono_method_set_generic_container (m, container);
12071 for (i = 0; i < count; i++) {
12072 MonoReflectionGenericParam *gp =
12073 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12074 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12075 mono_error_assert_ok (error);
12076 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12077 container->type_params [i] = *param;
12081 * The method signature might have pointers to generic parameters that belong to other methods.
12082 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12083 * generic parameters.
12085 for (i = 0; i < m->signature->param_count; ++i) {
12086 MonoType *t = m->signature->params [i];
12087 if (t->type == MONO_TYPE_MVAR) {
12088 MonoGenericParam *gparam = t->data.generic_param;
12089 if (gparam->num < count) {
12090 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12091 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12097 if (klass->generic_container) {
12098 container->parent = klass->generic_container;
12099 container->context.class_inst = klass->generic_container->context.class_inst;
12101 container->context.method_inst = mono_get_shared_generic_inst (container);
12105 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12109 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12111 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12112 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12113 for (i = 0; i < rmb->nrefs; ++i)
12114 data [i + 1] = rmb->refs [i];
12119 /* Parameter info */
12122 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12123 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12124 for (i = 0; i <= m->signature->param_count; ++i) {
12125 MonoReflectionParamBuilder *pb;
12126 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12127 if ((i > 0) && (pb->attrs)) {
12128 /* Make a copy since it might point to a shared type structure */
12129 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12130 m->signature->params [i - 1]->attrs = pb->attrs;
12133 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12134 MonoDynamicImage *assembly;
12136 MonoTypeEnum def_type;
12140 if (!method_aux->param_defaults) {
12141 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12142 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12144 assembly = (MonoDynamicImage*)klass->image;
12145 idx = encode_constant (assembly, pb->def_value, &def_type);
12146 /* Copy the data from the blob since it might get realloc-ed */
12147 p = assembly->blob.data + idx;
12148 len = mono_metadata_decode_blob_size (p, &p2);
12150 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12151 method_aux->param_default_types [i] = def_type;
12152 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12156 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12157 mono_error_assert_ok (error);
12160 if (!method_aux->param_cattr)
12161 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12162 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12168 /* Parameter marshalling */
12171 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12172 MonoReflectionParamBuilder *pb;
12173 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12174 if (pb->marshal_info) {
12176 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12177 specs [pb->position] =
12178 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12179 if (!is_ok (error)) {
12180 mono_loader_unlock ();
12181 image_g_free (image, specs);
12182 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12188 if (specs != NULL) {
12190 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12191 method_aux->param_marshall = specs;
12194 if (image_is_dynamic (klass->image) && method_aux)
12195 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12197 mono_loader_unlock ();
12203 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12205 ReflectionMethodBuilder rmb;
12206 MonoMethodSignature *sig;
12208 mono_loader_lock ();
12209 g_assert (klass->image != NULL);
12210 sig = ctor_builder_to_signature (klass->image, mb, error);
12211 mono_loader_unlock ();
12212 return_val_if_nok (error, NULL);
12214 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12217 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12218 return_val_if_nok (error, NULL);
12219 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12221 /* If we are in a generic class, we might be called multiple times from inflate_method */
12222 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12223 /* ilgen is no longer needed */
12227 return mb->mhandle;
12231 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12233 ReflectionMethodBuilder rmb;
12234 MonoMethodSignature *sig;
12236 mono_error_init (error);
12238 mono_loader_lock ();
12239 g_assert (klass->image != NULL);
12240 sig = method_builder_to_signature (klass->image, mb, error);
12241 mono_loader_unlock ();
12242 return_val_if_nok (error, NULL);
12244 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12247 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12248 return_val_if_nok (error, NULL);
12249 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12251 /* If we are in a generic class, we might be called multiple times from inflate_method */
12252 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12253 /* ilgen is no longer needed */
12256 return mb->mhandle;
12259 static MonoClassField*
12260 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12262 MonoClassField *field;
12265 mono_error_init (error);
12267 field = g_new0 (MonoClassField, 1);
12269 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12270 mono_error_assert_ok (error);
12271 if (fb->attrs || fb->modreq || fb->modopt) {
12272 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12273 if (!is_ok (error)) {
12277 field->type = mono_metadata_type_dup (NULL, type);
12278 field->type->attrs = fb->attrs;
12280 g_assert (image_is_dynamic (klass->image));
12281 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12282 g_free (field->type);
12283 if (!is_ok (error)) {
12287 field->type = mono_metadata_type_dup (klass->image, custom);
12290 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12291 if (!is_ok (error)) {
12296 if (fb->offset != -1)
12297 field->offset = fb->offset;
12298 field->parent = klass;
12299 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12301 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12308 * mono_reflection_bind_generic_parameters:
12309 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12310 * @type_args: the number of type arguments to bind
12311 * @types: array of type arguments
12312 * @error: set on error
12314 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12315 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12318 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12321 MonoReflectionTypeBuilder *tb = NULL;
12322 gboolean is_dynamic = FALSE;
12323 MonoClass *geninst;
12325 mono_error_init (error);
12327 mono_loader_lock ();
12329 if (is_sre_type_builder (mono_object_class (type))) {
12330 tb = (MonoReflectionTypeBuilder *) type;
12333 } else if (is_sre_generic_instance (mono_object_class (type))) {
12334 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12335 MonoReflectionType *gtd = rgi->generic_type;
12337 if (is_sre_type_builder (mono_object_class (gtd))) {
12338 tb = (MonoReflectionTypeBuilder *)gtd;
12343 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12344 if (tb && tb->generic_container) {
12345 if (!mono_reflection_create_generic_class (tb, error)) {
12346 mono_loader_unlock ();
12351 MonoType *t = mono_reflection_type_get_handle (type, error);
12352 if (!is_ok (error)) {
12353 mono_loader_unlock ();
12357 klass = mono_class_from_mono_type (t);
12358 if (!klass->generic_container) {
12359 mono_loader_unlock ();
12360 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12364 if (klass->wastypebuilder) {
12365 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12370 mono_loader_unlock ();
12372 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12374 return &geninst->byval_arg;
12378 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12380 MonoGenericClass *gclass;
12381 MonoGenericInst *inst;
12383 g_assert (klass->generic_container);
12385 inst = mono_metadata_get_generic_inst (type_argc, types);
12386 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12388 return mono_generic_class_get_class (gclass);
12391 static MonoReflectionMethod*
12392 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12395 MonoMethod *method, *inflated;
12396 MonoMethodInflated *imethod;
12397 MonoGenericContext tmp_context;
12398 MonoGenericInst *ginst;
12399 MonoType **type_argv;
12402 mono_error_init (error);
12404 /*FIXME but this no longer should happen*/
12405 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12406 #ifndef DISABLE_REFLECTION_EMIT
12407 MonoReflectionMethodBuilder *mb = NULL;
12411 mb = (MonoReflectionMethodBuilder *) rmethod;
12412 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12413 return_val_if_nok (error, NULL);
12414 klass = mono_class_from_mono_type (tb);
12416 method = methodbuilder_to_mono_method (klass, mb, error);
12417 return_val_if_nok (error, NULL);
12419 g_assert_not_reached ();
12423 method = rmethod->method;
12426 klass = method->klass;
12428 if (method->is_inflated)
12429 method = ((MonoMethodInflated *) method)->declaring;
12431 count = mono_method_signature (method)->generic_param_count;
12432 if (count != mono_array_length (types))
12435 type_argv = g_new0 (MonoType *, count);
12436 for (i = 0; i < count; i++) {
12437 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12438 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12439 if (!is_ok (error)) {
12440 g_free (type_argv);
12444 ginst = mono_metadata_get_generic_inst (count, type_argv);
12445 g_free (type_argv);
12447 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12448 tmp_context.method_inst = ginst;
12450 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12451 mono_error_assert_ok (error);
12452 imethod = (MonoMethodInflated *) inflated;
12454 /*FIXME but I think this is no longer necessary*/
12455 if (image_is_dynamic (method->klass->image)) {
12456 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12458 * This table maps metadata structures representing inflated methods/fields
12459 * to the reflection objects representing their generic definitions.
12461 mono_image_lock ((MonoImage*)image);
12462 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12463 mono_image_unlock ((MonoImage*)image);
12466 if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12467 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12471 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12475 MonoReflectionMethod*
12476 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12479 MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12480 mono_error_set_pending_exception (&error);
12485 #ifndef DISABLE_REFLECTION_EMIT
12487 static MonoMethod *
12488 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12490 MonoMethodInflated *imethod;
12491 MonoGenericContext *context;
12495 * With generic code sharing the klass might not be inflated.
12496 * This can happen because classes inflated with their own
12497 * type arguments are "normalized" to the uninflated class.
12499 if (!klass->generic_class)
12502 context = mono_class_get_context (klass);
12504 if (klass->method.count && klass->methods) {
12505 /* Find the already created inflated method */
12506 for (i = 0; i < klass->method.count; ++i) {
12507 g_assert (klass->methods [i]->is_inflated);
12508 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12511 g_assert (i < klass->method.count);
12512 imethod = (MonoMethodInflated*)klass->methods [i];
12515 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12516 mono_error_assert_ok (&error);
12519 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12520 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12522 mono_image_lock ((MonoImage*)image);
12523 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12524 mono_image_unlock ((MonoImage*)image);
12526 return (MonoMethod *) imethod;
12529 static MonoMethod *
12530 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12532 MonoMethod *method;
12535 mono_error_init (error);
12537 MonoClass *type_class = mono_object_class (type);
12539 if (is_sre_generic_instance (type_class)) {
12540 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12541 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12542 return_val_if_nok (error, NULL);
12543 gklass = mono_class_from_mono_type (generic_type);
12544 } else if (is_sre_type_builder (type_class)) {
12545 MonoType *t = mono_reflection_type_get_handle (type, error);
12546 return_val_if_nok (error, NULL);
12547 gklass = mono_class_from_mono_type (t);
12548 } else if (type->type) {
12549 gklass = mono_class_from_mono_type (type->type);
12550 gklass = mono_class_get_generic_type_definition (gklass);
12552 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12555 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12556 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12557 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12559 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12563 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12564 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12567 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12568 method = ((MonoReflectionMethod *) obj)->method;
12570 method = NULL; /* prevent compiler warning */
12571 g_error ("can't handle type %s", obj->vtable->klass->name);
12574 MonoType *t = mono_reflection_type_get_handle (type, error);
12575 return_val_if_nok (error, NULL);
12576 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12579 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12581 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12583 MonoGenericClass *gclass;
12584 MonoDynamicGenericClass *dgclass;
12585 MonoClass *klass, *gklass;
12589 mono_error_init (error);
12591 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12592 return_val_if_nok (error, FALSE);
12593 klass = mono_class_from_mono_type (gtype);
12594 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12595 gclass = gtype->data.generic_class;
12597 if (!gclass->is_dynamic)
12600 dgclass = (MonoDynamicGenericClass *) gclass;
12602 if (dgclass->initialized)
12605 gklass = gclass->container_class;
12606 mono_class_init (gklass);
12608 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12610 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12611 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12612 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12614 for (i = 0; i < dgclass->count_fields; i++) {
12615 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12616 MonoClassField *field, *inflated_field = NULL;
12618 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12619 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12620 return_val_if_nok (error, FALSE);
12621 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12622 field = ((MonoReflectionField *) obj)->field;
12624 field = NULL; /* prevent compiler warning */
12625 g_assert_not_reached ();
12628 dgclass->fields [i] = *field;
12629 dgclass->fields [i].parent = klass;
12630 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12631 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12632 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12633 dgclass->field_generic_types [i] = field->type;
12634 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12635 dgclass->field_objects [i] = obj;
12637 if (inflated_field) {
12638 g_free (inflated_field);
12640 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12644 dgclass->initialized = TRUE;
12649 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12652 (void) reflection_generic_class_initialize (type, fields, &error);
12653 mono_error_set_pending_exception (&error);
12657 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12659 MonoDynamicGenericClass *dgclass;
12662 g_assert (gclass->is_dynamic);
12664 dgclass = (MonoDynamicGenericClass *)gclass;
12666 for (i = 0; i < dgclass->count_fields; ++i) {
12667 MonoClassField *field = dgclass->fields + i;
12668 mono_metadata_free_type (field->type);
12669 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12674 * fix_partial_generic_class:
12675 * @klass: a generic instantiation MonoClass
12676 * @error: set on error
12678 * Assumes that the generic container of @klass has its vtable
12679 * initialized, and updates the parent class, insterfaces, methods and
12680 * fields of @klass by inflating the types using the generic context.
12682 * On success returns TRUE, on failure returns FALSE and sets @error.
12686 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12688 MonoClass *gklass = klass->generic_class->container_class;
12689 MonoDynamicGenericClass *dgclass;
12692 mono_error_init (error);
12694 if (klass->wastypebuilder)
12697 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12698 if (klass->parent != gklass->parent) {
12699 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12700 if (mono_error_ok (error)) {
12701 MonoClass *parent = mono_class_from_mono_type (parent_type);
12702 mono_metadata_free_type (parent_type);
12703 if (parent != klass->parent) {
12704 /*fool mono_class_setup_parent*/
12705 klass->supertypes = NULL;
12706 mono_class_setup_parent (klass, parent);
12709 if (gklass->wastypebuilder)
12710 klass->wastypebuilder = TRUE;
12715 if (!dgclass->initialized)
12718 if (klass->method.count != gklass->method.count) {
12719 klass->method.count = gklass->method.count;
12720 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12722 for (i = 0; i < klass->method.count; i++) {
12723 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12724 gklass->methods [i], klass, mono_class_get_context (klass), error);
12725 mono_error_assert_ok (error);
12729 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12730 klass->interface_count = gklass->interface_count;
12731 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12732 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12734 for (i = 0; i < gklass->interface_count; ++i) {
12735 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12736 return_val_if_nok (error, FALSE);
12738 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12739 mono_metadata_free_type (iface_type);
12741 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12744 klass->interfaces_inited = 1;
12747 if (klass->field.count != gklass->field.count) {
12748 klass->field.count = gklass->field.count;
12749 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12751 for (i = 0; i < klass->field.count; i++) {
12752 klass->fields [i] = gklass->fields [i];
12753 klass->fields [i].parent = klass;
12754 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12755 return_val_if_nok (error, FALSE);
12759 /*We can only finish with this klass once it's parent has as well*/
12760 if (gklass->wastypebuilder)
12761 klass->wastypebuilder = TRUE;
12766 * ensure_generic_class_runtime_vtable:
12767 * @klass a generic class
12768 * @error set on error
12770 * Ensures that the generic container of @klass has a vtable and
12771 * returns TRUE on success. On error returns FALSE and sets @error.
12774 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12776 MonoClass *gklass = klass->generic_class->container_class;
12778 mono_error_init (error);
12780 if (!ensure_runtime_vtable (gklass, error))
12783 return fix_partial_generic_class (klass, error);
12787 * ensure_runtime_vtable:
12789 * @error set on error
12791 * Ensures that @klass has a vtable and returns TRUE on success. On
12792 * error returns FALSE and sets @error.
12795 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12797 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12800 mono_error_init (error);
12802 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12805 if (!ensure_runtime_vtable (klass->parent, error))
12809 num = tb->ctors? mono_array_length (tb->ctors): 0;
12810 num += tb->num_methods;
12811 klass->method.count = num;
12812 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12813 num = tb->ctors? mono_array_length (tb->ctors): 0;
12814 for (i = 0; i < num; ++i) {
12815 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12818 klass->methods [i] = ctor;
12820 num = tb->num_methods;
12822 for (i = 0; i < num; ++i) {
12823 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12826 klass->methods [j++] = meth;
12829 if (tb->interfaces) {
12830 klass->interface_count = mono_array_length (tb->interfaces);
12831 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12832 for (i = 0; i < klass->interface_count; ++i) {
12833 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12834 return_val_if_nok (error, FALSE);
12835 klass->interfaces [i] = mono_class_from_mono_type (iface);
12836 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12839 klass->interfaces_inited = 1;
12841 } else if (klass->generic_class){
12842 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12843 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12848 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12850 for (i = 0; i < klass->method.count; ++i) {
12851 MonoMethod *im = klass->methods [i];
12852 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12853 im->slot = slot_num++;
12856 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12857 mono_class_setup_interface_offsets (klass);
12858 mono_class_setup_interface_id (klass);
12862 * The generic vtable is needed even if image->run is not set since some
12863 * runtime code like ves_icall_Type_GetMethodsByName depends on
12864 * method->slot being defined.
12868 * tb->methods could not be freed since it is used for determining
12869 * overrides during dynamic vtable construction.
12876 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12878 mono_error_init (error);
12879 MonoClass *klass = mono_object_class (method);
12880 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12881 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12882 return sr_method->method;
12884 if (is_sre_method_builder (klass)) {
12885 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12886 return mb->mhandle;
12888 if (is_sre_method_on_tb_inst (klass)) {
12889 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12890 MonoMethod *result;
12891 /*FIXME move this to a proper method and unify with resolve_object*/
12892 if (m->method_args) {
12893 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12895 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12896 return_val_if_nok (error, NULL);
12897 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12898 MonoMethod *mono_method;
12900 if (is_sre_method_builder (mono_object_class (m->mb)))
12901 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12902 else if (is_sr_mono_method (mono_object_class (m->mb)))
12903 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12905 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)));
12907 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12912 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12917 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12919 MonoReflectionTypeBuilder *tb;
12921 MonoReflectionMethod *m;
12923 mono_error_init (error);
12925 *num_overrides = 0;
12927 g_assert (image_is_dynamic (klass->image));
12929 if (!mono_class_get_ref_info (klass))
12932 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12934 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12938 for (i = 0; i < tb->num_methods; ++i) {
12939 MonoReflectionMethodBuilder *mb =
12940 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12941 if (mb->override_methods)
12942 onum += mono_array_length (mb->override_methods);
12947 *overrides = g_new0 (MonoMethod*, onum * 2);
12950 for (i = 0; i < tb->num_methods; ++i) {
12951 MonoReflectionMethodBuilder *mb =
12952 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12953 if (mb->override_methods) {
12954 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12955 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12957 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12958 return_if_nok (error);
12959 (*overrides) [onum * 2 + 1] = mb->mhandle;
12961 g_assert (mb->mhandle);
12969 *num_overrides = onum;
12973 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12975 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12976 MonoReflectionFieldBuilder *fb;
12977 MonoClassField *field;
12978 MonoImage *image = klass->image;
12979 const char *p, *p2;
12981 guint32 len, idx, real_size = 0;
12983 klass->field.count = tb->num_fields;
12984 klass->field.first = 0;
12986 mono_error_init (error);
12988 if (tb->class_size) {
12989 if ((tb->packing_size & 0xffffff00) != 0) {
12990 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12991 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12994 klass->packing_size = tb->packing_size;
12995 real_size = klass->instance_size + tb->class_size;
12998 if (!klass->field.count) {
12999 klass->instance_size = MAX (klass->instance_size, real_size);
13003 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
13004 mono_class_alloc_ext (klass);
13005 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
13007 This is, guess what, a hack.
13008 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
13009 On the static path no field class is resolved, only types are built. This is the right thing to do
13011 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
13013 klass->size_inited = 1;
13015 for (i = 0; i < klass->field.count; ++i) {
13016 MonoArray *rva_data;
13017 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13018 field = &klass->fields [i];
13019 field->name = mono_string_to_utf8_image (image, fb->name, error);
13020 if (!mono_error_ok (error))
13023 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13024 return_if_nok (error);
13025 field->type = mono_metadata_type_dup (klass->image, type);
13026 field->type->attrs = fb->attrs;
13028 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13029 return_if_nok (error);
13032 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
13033 char *base = mono_array_addr (rva_data, char, 0);
13034 size_t size = mono_array_length (rva_data);
13035 char *data = (char *)mono_image_alloc (klass->image, size);
13036 memcpy (data, base, size);
13037 klass->ext->field_def_values [i].data = data;
13039 if (fb->offset != -1)
13040 field->offset = fb->offset;
13041 field->parent = klass;
13042 fb->handle = field;
13043 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13045 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13046 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13048 if (fb->def_value) {
13049 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13050 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13051 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13052 /* Copy the data from the blob since it might get realloc-ed */
13053 p = assembly->blob.data + idx;
13054 len = mono_metadata_decode_blob_size (p, &p2);
13056 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13057 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13061 klass->instance_size = MAX (klass->instance_size, real_size);
13062 mono_class_layout_fields (klass, klass->instance_size);
13066 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13068 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13069 MonoReflectionPropertyBuilder *pb;
13070 MonoImage *image = klass->image;
13071 MonoProperty *properties;
13074 mono_error_init (error);
13077 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13079 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13080 klass->ext->property.first = 0;
13082 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13083 klass->ext->properties = properties;
13084 for (i = 0; i < klass->ext->property.count; ++i) {
13085 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13086 properties [i].parent = klass;
13087 properties [i].attrs = pb->attrs;
13088 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13089 if (!mono_error_ok (error))
13091 if (pb->get_method)
13092 properties [i].get = pb->get_method->mhandle;
13093 if (pb->set_method)
13094 properties [i].set = pb->set_method->mhandle;
13096 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13097 if (pb->def_value) {
13099 const char *p, *p2;
13100 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13101 if (!klass->ext->prop_def_values)
13102 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13103 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13104 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13105 /* Copy the data from the blob since it might get realloc-ed */
13106 p = assembly->blob.data + idx;
13107 len = mono_metadata_decode_blob_size (p, &p2);
13109 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13110 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13115 static MonoReflectionEvent *
13116 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13118 mono_error_init (error);
13120 MonoEvent *event = g_new0 (MonoEvent, 1);
13123 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13124 if (!is_ok (error)) {
13128 klass = mono_class_from_mono_type (type);
13130 event->parent = klass;
13131 event->attrs = eb->attrs;
13132 event->name = mono_string_to_utf8_checked (eb->name, error);
13133 if (!is_ok (error)) {
13137 if (eb->add_method)
13138 event->add = eb->add_method->mhandle;
13139 if (eb->remove_method)
13140 event->remove = eb->remove_method->mhandle;
13141 if (eb->raise_method)
13142 event->raise = eb->raise_method->mhandle;
13144 #ifndef MONO_SMALL_CONFIG
13145 if (eb->other_methods) {
13147 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13148 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13149 MonoReflectionMethodBuilder *mb =
13150 mono_array_get (eb->other_methods,
13151 MonoReflectionMethodBuilder*, j);
13152 event->other [j] = mb->mhandle;
13157 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13158 if (!is_ok (error)) {
13159 #ifndef MONO_SMALL_CONFIG
13160 g_free (event->other);
13168 MonoReflectionEvent *
13169 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13172 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13173 mono_error_set_pending_exception (&error);
13178 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13180 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13181 MonoReflectionEventBuilder *eb;
13182 MonoImage *image = klass->image;
13186 mono_error_init (error);
13189 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13191 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13192 klass->ext->event.first = 0;
13194 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13195 klass->ext->events = events;
13196 for (i = 0; i < klass->ext->event.count; ++i) {
13197 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13198 events [i].parent = klass;
13199 events [i].attrs = eb->attrs;
13200 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13201 if (!mono_error_ok (error))
13203 if (eb->add_method)
13204 events [i].add = eb->add_method->mhandle;
13205 if (eb->remove_method)
13206 events [i].remove = eb->remove_method->mhandle;
13207 if (eb->raise_method)
13208 events [i].raise = eb->raise_method->mhandle;
13210 #ifndef MONO_SMALL_CONFIG
13211 if (eb->other_methods) {
13213 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13214 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13215 MonoReflectionMethodBuilder *mb =
13216 mono_array_get (eb->other_methods,
13217 MonoReflectionMethodBuilder*, j);
13218 events [i].other [j] = mb->mhandle;
13222 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13226 struct remove_instantiations_user_data
13233 remove_instantiations_of_and_ensure_contents (gpointer key,
13235 gpointer user_data)
13237 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13238 MonoType *type = (MonoType*)key;
13239 MonoClass *klass = data->klass;
13240 gboolean already_failed = !is_ok (data->error);
13242 MonoError *error = already_failed ? &lerror : data->error;
13244 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13245 MonoClass *inst_klass = mono_class_from_mono_type (type);
13246 //Ensure it's safe to use it.
13247 if (!fix_partial_generic_class (inst_klass, error)) {
13248 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13249 // Marked the class with failure, but since some other instantiation already failed,
13250 // just report that one, and swallow the error from this one.
13251 if (already_failed)
13252 mono_error_cleanup (error);
13260 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13262 mono_error_init (error);
13268 for (i = 0; i < mono_array_length (arr); ++i) {
13269 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13270 if (!mono_error_ok (error))
13275 MonoReflectionType*
13276 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13280 MonoDomain* domain;
13281 MonoReflectionType* res;
13284 mono_error_init (&error);
13286 domain = mono_object_domain (tb);
13287 klass = mono_class_from_mono_type (tb->type.type);
13290 * Check for user defined Type subclasses.
13292 RESOLVE_TYPE (tb->parent, &error);
13293 if (!is_ok (&error))
13294 goto failure_unlocked;
13295 check_array_for_usertypes (tb->interfaces, &error);
13296 if (!is_ok (&error))
13297 goto failure_unlocked;
13299 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13300 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13302 RESOLVE_TYPE (fb->type, &error);
13303 if (!is_ok (&error))
13304 goto failure_unlocked;
13305 check_array_for_usertypes (fb->modreq, &error);
13306 if (!is_ok (&error))
13307 goto failure_unlocked;
13308 check_array_for_usertypes (fb->modopt, &error);
13309 if (!is_ok (&error))
13310 goto failure_unlocked;
13311 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13312 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13313 if (!is_ok (&error))
13314 goto failure_unlocked;
13320 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13321 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13323 RESOLVE_TYPE (mb->rtype, &error);
13324 if (!is_ok (&error))
13325 goto failure_unlocked;
13326 check_array_for_usertypes (mb->return_modreq, &error);
13327 if (!is_ok (&error))
13328 goto failure_unlocked;
13329 check_array_for_usertypes (mb->return_modopt, &error);
13330 if (!is_ok (&error))
13331 goto failure_unlocked;
13332 check_array_for_usertypes (mb->parameters, &error);
13333 if (!is_ok (&error))
13334 goto failure_unlocked;
13335 if (mb->param_modreq)
13336 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13337 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13338 if (!is_ok (&error))
13339 goto failure_unlocked;
13341 if (mb->param_modopt)
13342 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13343 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13344 if (!is_ok (&error))
13345 goto failure_unlocked;
13351 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13352 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13354 check_array_for_usertypes (mb->parameters, &error);
13355 if (!is_ok (&error))
13356 goto failure_unlocked;
13357 if (mb->param_modreq)
13358 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13359 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13360 if (!is_ok (&error))
13361 goto failure_unlocked;
13363 if (mb->param_modopt)
13364 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13365 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13366 if (!is_ok (&error))
13367 goto failure_unlocked;
13373 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13376 * we need to lock the domain because the lock will be taken inside
13377 * So, we need to keep the locking order correct.
13379 mono_loader_lock ();
13380 mono_domain_lock (domain);
13381 if (klass->wastypebuilder) {
13382 mono_domain_unlock (domain);
13383 mono_loader_unlock ();
13385 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13386 mono_error_set_pending_exception (&error);
13391 * Fields to set in klass:
13392 * the various flags: delegate/unicode/contextbound etc.
13394 klass->flags = tb->attrs;
13395 klass->has_cctor = 1;
13397 mono_class_setup_parent (klass, klass->parent);
13398 /* fool mono_class_setup_supertypes */
13399 klass->supertypes = NULL;
13400 mono_class_setup_supertypes (klass);
13401 mono_class_setup_mono_type (klass);
13404 if (!((MonoDynamicImage*)klass->image)->run) {
13405 if (klass->generic_container) {
13406 /* FIXME: The code below can't handle generic classes */
13407 klass->wastypebuilder = TRUE;
13408 mono_loader_unlock ();
13409 mono_domain_unlock (domain);
13411 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13412 mono_error_set_pending_exception (&error);
13419 /* enums are done right away */
13420 if (!klass->enumtype)
13421 if (!ensure_runtime_vtable (klass, &error))
13424 if (tb->subtypes) {
13425 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13426 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13427 mono_class_alloc_ext (klass);
13428 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13429 if (!is_ok (&error)) goto failure;
13430 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13434 klass->nested_classes_inited = TRUE;
13436 /* fields and object layout */
13437 if (klass->parent) {
13438 if (!klass->parent->size_inited)
13439 mono_class_init (klass->parent);
13440 klass->instance_size = klass->parent->instance_size;
13441 klass->sizes.class_size = 0;
13442 klass->min_align = klass->parent->min_align;
13443 /* if the type has no fields we won't call the field_setup
13444 * routine which sets up klass->has_references.
13446 klass->has_references |= klass->parent->has_references;
13448 klass->instance_size = sizeof (MonoObject);
13449 klass->min_align = 1;
13452 /* FIXME: handle packing_size and instance_size */
13453 typebuilder_setup_fields (klass, &error);
13454 if (!mono_error_ok (&error))
13456 typebuilder_setup_properties (klass, &error);
13457 if (!mono_error_ok (&error))
13460 typebuilder_setup_events (klass, &error);
13461 if (!mono_error_ok (&error))
13464 klass->wastypebuilder = TRUE;
13467 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13468 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13469 * we want to return normal System.MonoType objects, so clear these out from the cache.
13471 * Together with this we must ensure the contents of all instances to match the created type.
13473 if (domain->type_hash && klass->generic_container) {
13474 struct remove_instantiations_user_data data;
13475 data.klass = klass;
13476 data.error = &error;
13477 mono_error_assert_ok (&error);
13478 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13479 if (!is_ok (&error))
13483 mono_domain_unlock (domain);
13484 mono_loader_unlock ();
13486 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13487 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13488 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13489 goto failure_unlocked;
13492 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13493 if (!is_ok (&error))
13494 goto failure_unlocked;
13496 g_assert (res != (MonoReflectionType*)tb);
13501 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13502 klass->wastypebuilder = TRUE;
13503 mono_domain_unlock (domain);
13504 mono_loader_unlock ();
13506 mono_error_set_pending_exception (&error);
13511 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13513 MonoGenericParamFull *param;
13517 mono_error_init (error);
13519 image = &gparam->tbuilder->module->dynamic_image->image;
13521 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13523 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13524 mono_error_assert_ok (error);
13525 param->param.num = gparam->index;
13527 if (gparam->mbuilder) {
13528 if (!gparam->mbuilder->generic_container) {
13529 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13530 return_val_if_nok (error, FALSE);
13532 MonoClass *klass = mono_class_from_mono_type (tb);
13533 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13534 gparam->mbuilder->generic_container->is_method = TRUE;
13536 * Cannot set owner.method, since the MonoMethod is not created yet.
13537 * Set the image field instead, so type_in_image () works.
13539 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13540 gparam->mbuilder->generic_container->owner.image = klass->image;
13542 param->param.owner = gparam->mbuilder->generic_container;
13543 } else if (gparam->tbuilder) {
13544 if (!gparam->tbuilder->generic_container) {
13545 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13546 return_val_if_nok (error, FALSE);
13547 MonoClass *klass = mono_class_from_mono_type (tb);
13548 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13549 gparam->tbuilder->generic_container->owner.klass = klass;
13551 param->param.owner = gparam->tbuilder->generic_container;
13554 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13556 gparam->type.type = &pklass->byval_arg;
13558 mono_class_set_ref_info (pklass, gparam);
13559 mono_image_append_class_to_reflection_info_set (pklass);
13565 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13568 (void) reflection_initialize_generic_parameter (gparam, &error);
13569 mono_error_set_pending_exception (&error);
13574 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13576 MonoReflectionModuleBuilder *module = sig->module;
13577 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13578 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13583 mono_error_init (error);
13585 check_array_for_usertypes (sig->arguments, error);
13586 return_val_if_nok (error, NULL);
13588 sigbuffer_init (&buf, 32);
13590 sigbuffer_add_value (&buf, 0x07);
13591 sigbuffer_add_value (&buf, na);
13592 if (assembly != NULL){
13593 for (i = 0; i < na; ++i) {
13594 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13595 encode_reflection_type (assembly, type, &buf, error);
13596 if (!is_ok (error)) goto fail;
13600 buflen = buf.p - buf.buf;
13601 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13602 if (!is_ok (error)) goto fail;
13603 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13604 sigbuffer_free (&buf);
13607 sigbuffer_free (&buf);
13612 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13615 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13616 mono_error_set_pending_exception (&error);
13621 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13623 MonoDynamicImage *assembly = sig->module->dynamic_image;
13624 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13629 mono_error_init (error);
13631 check_array_for_usertypes (sig->arguments, error);
13632 return_val_if_nok (error, NULL);
13634 sigbuffer_init (&buf, 32);
13636 sigbuffer_add_value (&buf, 0x06);
13637 for (i = 0; i < na; ++i) {
13638 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13639 encode_reflection_type (assembly, type, &buf, error);
13640 if (!is_ok (error))
13644 buflen = buf.p - buf.buf;
13645 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13646 if (!is_ok (error)) goto fail;
13647 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13648 sigbuffer_free (&buf);
13652 sigbuffer_free (&buf);
13657 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13660 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13661 mono_error_set_pending_exception (&error);
13666 MonoMethod *handle;
13667 MonoDomain *domain;
13668 } DynamicMethodReleaseData;
13671 * The runtime automatically clean up those after finalization.
13673 static MonoReferenceQueue *dynamic_method_queue;
13676 free_dynamic_method (void *dynamic_method)
13678 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13679 MonoDomain *domain = data->domain;
13680 MonoMethod *method = data->handle;
13683 mono_domain_lock (domain);
13684 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13685 g_hash_table_remove (domain->method_to_dyn_method, method);
13686 mono_domain_unlock (domain);
13687 g_assert (dis_link);
13688 mono_gchandle_free (dis_link);
13690 mono_runtime_free_method (domain, method);
13695 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13697 MonoReferenceQueue *queue;
13698 MonoMethod *handle;
13699 DynamicMethodReleaseData *release_data;
13700 ReflectionMethodBuilder rmb;
13701 MonoMethodSignature *sig;
13703 MonoDomain *domain;
13707 mono_error_init (error);
13709 if (mono_runtime_is_shutting_down ()) {
13710 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13714 if (!(queue = dynamic_method_queue)) {
13715 mono_loader_lock ();
13716 if (!(queue = dynamic_method_queue))
13717 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13718 mono_loader_unlock ();
13721 sig = dynamic_method_to_signature (mb, error);
13722 return_val_if_nok (error, FALSE);
13724 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13727 * Resolve references.
13730 * Every second entry in the refs array is reserved for storing handle_class,
13731 * which is needed by the ldtoken implementation in the JIT.
13733 rmb.nrefs = mb->nrefs;
13734 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13735 for (i = 0; i < mb->nrefs; i += 2) {
13736 MonoClass *handle_class;
13738 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13740 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13741 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13743 * The referenced DynamicMethod should already be created by the managed
13744 * code, except in the case of circular references. In that case, we store
13745 * method in the refs array, and fix it up later when the referenced
13746 * DynamicMethod is created.
13748 if (method->mhandle) {
13749 ref = method->mhandle;
13751 /* FIXME: GC object stored in unmanaged memory */
13754 /* FIXME: GC object stored in unmanaged memory */
13755 method->referenced_by = g_slist_append (method->referenced_by, mb);
13757 handle_class = mono_defaults.methodhandle_class;
13759 MonoException *ex = NULL;
13760 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13761 if (!is_ok (error)) {
13766 ex = mono_get_exception_type_load (NULL, NULL);
13767 else if (mono_security_core_clr_enabled ())
13768 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13772 mono_error_set_exception_instance (error, ex);
13777 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13778 rmb.refs [i + 1] = handle_class;
13782 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13783 if (!is_ok (error)) {
13787 klass = mono_class_from_mono_type (owner_type);
13789 klass = mono_defaults.object_class;
13792 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13794 return_val_if_nok (error, FALSE);
13796 release_data = g_new (DynamicMethodReleaseData, 1);
13797 release_data->handle = handle;
13798 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13799 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13800 g_free (release_data);
13802 /* Fix up refs entries pointing at us */
13803 for (l = mb->referenced_by; l; l = l->next) {
13804 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13805 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13808 g_assert (method->mhandle);
13810 data = (gpointer*)wrapper->method_data;
13811 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13812 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13813 data [i + 1] = mb->mhandle;
13816 g_slist_free (mb->referenced_by);
13818 /* ilgen is no longer needed */
13821 domain = mono_domain_get ();
13822 mono_domain_lock (domain);
13823 if (!domain->method_to_dyn_method)
13824 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13825 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13826 mono_domain_unlock (domain);
13832 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13835 (void) reflection_create_dynamic_method (mb, &error);
13836 mono_error_set_pending_exception (&error);
13839 #endif /* DISABLE_REFLECTION_EMIT */
13843 * mono_reflection_is_valid_dynamic_token:
13845 * Returns TRUE if token is valid.
13849 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13851 return lookup_dyn_token (image, token) != NULL;
13854 MonoMethodSignature *
13855 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13857 MonoMethodSignature *sig;
13858 g_assert (image_is_dynamic (image));
13860 mono_error_init (error);
13862 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13866 return mono_method_signature_checked (method, error);
13869 #ifndef DISABLE_REFLECTION_EMIT
13872 * mono_reflection_lookup_dynamic_token:
13874 * Finish the Builder object pointed to by TOKEN and return the corresponding
13875 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13876 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13879 * LOCKING: Take the loader lock
13882 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13884 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13888 mono_error_init (error);
13890 obj = lookup_dyn_token (assembly, token);
13893 g_error ("Could not find required dynamic token 0x%08x", token);
13895 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13901 handle_class = &klass;
13902 gpointer result = resolve_object (image, obj, handle_class, context, error);
13907 * ensure_complete_type:
13909 * Ensure that KLASS is completed if it is a dynamic type, or references
13913 ensure_complete_type (MonoClass *klass, MonoError *error)
13915 mono_error_init (error);
13917 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13918 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13920 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13921 return_if_nok (error);
13923 // Asserting here could break a lot of code
13924 //g_assert (klass->wastypebuilder);
13927 if (klass->generic_class) {
13928 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13931 for (i = 0; i < inst->type_argc; ++i) {
13932 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13933 return_if_nok (error);
13939 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13941 gpointer result = NULL;
13943 mono_error_init (error);
13945 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13946 result = mono_string_intern_checked ((MonoString*)obj, error);
13947 return_val_if_nok (error, NULL);
13948 *handle_class = mono_defaults.string_class;
13950 } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13951 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13952 return_val_if_nok (error, NULL);
13953 MonoClass *mc = mono_class_from_mono_type (type);
13954 if (!mono_class_init (mc)) {
13955 mono_error_set_for_class_failure (error, mc);
13960 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13961 return_val_if_nok (error, NULL);
13963 result = mono_class_from_mono_type (inflated);
13964 mono_metadata_free_type (inflated);
13966 result = mono_class_from_mono_type (type);
13968 *handle_class = mono_defaults.typehandle_class;
13970 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13971 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13972 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13973 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13974 result = ((MonoReflectionMethod*)obj)->method;
13976 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13977 mono_error_assert_ok (error);
13979 *handle_class = mono_defaults.methodhandle_class;
13981 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13982 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13983 result = mb->mhandle;
13985 /* Type is not yet created */
13986 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13988 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13989 return_val_if_nok (error, NULL);
13992 * Hopefully this has been filled in by calling CreateType() on the
13996 * TODO: This won't work if the application finishes another
13997 * TypeBuilder instance instead of this one.
13999 result = mb->mhandle;
14002 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14003 mono_error_assert_ok (error);
14005 *handle_class = mono_defaults.methodhandle_class;
14006 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
14007 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
14009 result = cb->mhandle;
14011 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
14013 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14014 return_val_if_nok (error, NULL);
14015 result = cb->mhandle;
14018 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14019 mono_error_assert_ok (error);
14021 *handle_class = mono_defaults.methodhandle_class;
14022 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
14023 MonoClassField *field = ((MonoReflectionField*)obj)->field;
14025 ensure_complete_type (field->parent, error);
14026 return_val_if_nok (error, NULL);
14029 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
14030 return_val_if_nok (error, NULL);
14032 MonoClass *klass = mono_class_from_mono_type (inflated);
14033 MonoClassField *inflated_field;
14034 gpointer iter = NULL;
14035 mono_metadata_free_type (inflated);
14036 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
14037 if (!strcmp (field->name, inflated_field->name))
14040 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
14041 result = inflated_field;
14045 *handle_class = mono_defaults.fieldhandle_class;
14047 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14048 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14049 result = fb->handle;
14052 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14054 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14055 return_val_if_nok (error, NULL);
14056 result = fb->handle;
14059 if (fb->handle && fb->handle->parent->generic_container) {
14060 MonoClass *klass = fb->handle->parent;
14061 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14062 return_val_if_nok (error, NULL);
14064 MonoClass *inflated = mono_class_from_mono_type (type);
14066 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14068 mono_metadata_free_type (type);
14070 *handle_class = mono_defaults.fieldhandle_class;
14071 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14072 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14073 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14074 return_val_if_nok (error, NULL);
14077 klass = type->data.klass;
14078 if (klass->wastypebuilder) {
14079 /* Already created */
14083 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14084 return_val_if_nok (error, NULL);
14085 result = type->data.klass;
14088 *handle_class = mono_defaults.typehandle_class;
14089 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14090 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14091 MonoMethodSignature *sig;
14094 if (helper->arguments)
14095 nargs = mono_array_length (helper->arguments);
14099 sig = mono_metadata_signature_alloc (image, nargs);
14100 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14101 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14103 if (helper->unmanaged_call_conv) { /* unmanaged */
14104 sig->call_convention = helper->unmanaged_call_conv - 1;
14105 sig->pinvoke = TRUE;
14106 } else if (helper->call_conv & 0x02) {
14107 sig->call_convention = MONO_CALL_VARARG;
14109 sig->call_convention = MONO_CALL_DEFAULT;
14112 sig->param_count = nargs;
14113 /* TODO: Copy type ? */
14114 sig->ret = helper->return_type->type;
14115 for (i = 0; i < nargs; ++i) {
14116 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14117 if (!is_ok (error)) {
14118 image_g_free (image, sig);
14124 *handle_class = NULL;
14125 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14126 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14127 /* Already created by the managed code */
14128 g_assert (method->mhandle);
14129 result = method->mhandle;
14130 *handle_class = mono_defaults.methodhandle_class;
14131 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14132 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14133 return_val_if_nok (error, NULL);
14134 type = mono_class_inflate_generic_type_checked (type, context, error);
14135 return_val_if_nok (error, NULL);
14137 result = mono_class_from_mono_type (type);
14138 *handle_class = mono_defaults.typehandle_class;
14140 mono_metadata_free_type (type);
14141 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14142 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14143 return_val_if_nok (error, NULL);
14144 type = mono_class_inflate_generic_type_checked (type, context, error);
14145 return_val_if_nok (error, NULL);
14147 result = mono_class_from_mono_type (type);
14148 *handle_class = mono_defaults.typehandle_class;
14150 mono_metadata_free_type (type);
14151 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14152 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14153 MonoClass *inflated;
14155 MonoClassField *field;
14157 if (is_sre_field_builder (mono_object_class (f->fb)))
14158 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14159 else if (is_sr_mono_field (mono_object_class (f->fb)))
14160 field = ((MonoReflectionField*)f->fb)->field;
14162 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)));
14164 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14165 return_val_if_nok (error, NULL);
14166 type = mono_class_inflate_generic_type_checked (finst, context, error);
14167 return_val_if_nok (error, NULL);
14169 inflated = mono_class_from_mono_type (type);
14171 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14172 ensure_complete_type (field->parent, error);
14173 if (!is_ok (error)) {
14174 mono_metadata_free_type (type);
14179 mono_metadata_free_type (type);
14180 *handle_class = mono_defaults.fieldhandle_class;
14181 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14182 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14183 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14184 return_val_if_nok (error, NULL);
14185 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14186 return_val_if_nok (error, NULL);
14188 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14189 MonoMethod *method;
14191 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14192 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14193 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14194 method = ((MonoReflectionMethod *)c->cb)->method;
14196 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)));
14198 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14199 *handle_class = mono_defaults.methodhandle_class;
14200 mono_metadata_free_type (type);
14201 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14202 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14203 if (m->method_args) {
14204 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14205 return_val_if_nok (error, NULL);
14207 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14208 mono_error_assert_ok (error);
14211 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14212 return_val_if_nok (error, NULL);
14213 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14214 return_val_if_nok (error, NULL);
14216 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14217 MonoMethod *method;
14219 if (is_sre_method_builder (mono_object_class (m->mb)))
14220 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14221 else if (is_sr_mono_method (mono_object_class (m->mb)))
14222 method = ((MonoReflectionMethod *)m->mb)->method;
14224 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)));
14226 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14227 mono_metadata_free_type (type);
14229 *handle_class = mono_defaults.methodhandle_class;
14230 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14231 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14234 MonoMethod *method;
14238 mtype = mono_reflection_type_get_handle (m->parent, error);
14239 return_val_if_nok (error, NULL);
14240 klass = mono_class_from_mono_type (mtype);
14242 /* Find the method */
14244 name = mono_string_to_utf8_checked (m->name, error);
14245 return_val_if_nok (error, NULL);
14247 while ((method = mono_class_get_methods (klass, &iter))) {
14248 if (!strcmp (method->name, name))
14255 // FIXME: Check parameters/return value etc. match
14258 *handle_class = mono_defaults.methodhandle_class;
14259 } else if (is_sre_array (mono_object_get_class(obj)) ||
14260 is_sre_byref (mono_object_get_class(obj)) ||
14261 is_sre_pointer (mono_object_get_class(obj))) {
14262 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14263 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14264 return_val_if_nok (error, NULL);
14267 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14268 return_val_if_nok (error, NULL);
14270 result = mono_class_from_mono_type (inflated);
14271 mono_metadata_free_type (inflated);
14273 result = mono_class_from_mono_type (type);
14275 *handle_class = mono_defaults.typehandle_class;
14277 g_print ("%s\n", obj->vtable->klass->name);
14278 g_assert_not_reached ();
14283 #else /* DISABLE_REFLECTION_EMIT */
14286 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14288 g_assert_not_reached ();
14293 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14295 g_assert_not_reached ();
14299 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14301 g_assert_not_reached ();
14305 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14307 g_assert_not_reached ();
14312 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14314 g_assert_not_reached ();
14318 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14320 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14324 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14326 g_assert_not_reached ();
14330 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14332 g_assert_not_reached ();
14335 MonoReflectionModule *
14336 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14338 g_assert_not_reached ();
14343 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14345 g_assert_not_reached ();
14350 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14352 g_assert_not_reached ();
14357 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14358 gboolean create_open_instance, gboolean register_token, MonoError *error)
14360 g_assert_not_reached ();
14365 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14370 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14372 g_assert_not_reached ();
14376 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14378 mono_error_init (error);
14380 *num_overrides = 0;
14383 MonoReflectionEvent *
14384 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14386 g_assert_not_reached ();
14390 MonoReflectionType*
14391 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14393 g_assert_not_reached ();
14398 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14400 g_assert_not_reached ();
14404 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14406 g_assert_not_reached ();
14411 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14413 g_assert_not_reached ();
14418 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14423 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14425 mono_error_init (error);
14430 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14432 mono_error_init (error);
14439 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14441 g_assert_not_reached ();
14444 #endif /* DISABLE_REFLECTION_EMIT */
14446 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14447 const static guint32 declsec_flags_map[] = {
14448 0x00000000, /* empty */
14449 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14450 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14451 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14452 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14453 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14454 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14455 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14456 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14457 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14458 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14459 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14460 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14461 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14462 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14463 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14464 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14465 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14466 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14470 * Returns flags that includes all available security action associated to the handle.
14471 * @token: metadata token (either for a class or a method)
14472 * @image: image where resides the metadata.
14475 mono_declsec_get_flags (MonoImage *image, guint32 token)
14477 int index = mono_metadata_declsec_from_index (image, token);
14478 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14479 guint32 result = 0;
14483 /* HasSecurity can be present for other, not specially encoded, attributes,
14484 e.g. SuppressUnmanagedCodeSecurityAttribute */
14488 for (i = index; i < t->rows; i++) {
14489 guint32 cols [MONO_DECL_SECURITY_SIZE];
14491 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14492 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14495 action = cols [MONO_DECL_SECURITY_ACTION];
14496 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14497 result |= declsec_flags_map [action];
14499 g_assert_not_reached ();
14506 * Get the security actions (in the form of flags) associated with the specified method.
14508 * @method: The method for which we want the declarative security flags.
14509 * Return the declarative security flags for the method (only).
14511 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14512 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14515 mono_declsec_flags_from_method (MonoMethod *method)
14517 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14518 /* FIXME: No cache (for the moment) */
14519 guint32 idx = mono_method_get_index (method);
14520 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14521 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14522 return mono_declsec_get_flags (method->klass->image, idx);
14528 * Get the security actions (in the form of flags) associated with the specified class.
14530 * @klass: The class for which we want the declarative security flags.
14531 * Return the declarative security flags for the class.
14533 * Note: We cache the flags inside the MonoClass structure as this will get
14534 * called very often (at least for each method).
14537 mono_declsec_flags_from_class (MonoClass *klass)
14539 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14540 if (!klass->ext || !klass->ext->declsec_flags) {
14543 idx = mono_metadata_token_index (klass->type_token);
14544 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14545 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14546 mono_loader_lock ();
14547 mono_class_alloc_ext (klass);
14548 mono_loader_unlock ();
14549 /* we cache the flags on classes */
14550 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14552 return klass->ext->declsec_flags;
14558 * Get the security actions (in the form of flags) associated with the specified assembly.
14560 * @assembly: The assembly for which we want the declarative security flags.
14561 * Return the declarative security flags for the assembly.
14564 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14566 guint32 idx = 1; /* there is only one assembly */
14567 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14568 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14569 return mono_declsec_get_flags (assembly->image, idx);
14574 * Fill actions for the specific index (which may either be an encoded class token or
14575 * an encoded method token) from the metadata image.
14576 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14579 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14580 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14582 MonoBoolean result = FALSE;
14584 guint32 cols [MONO_DECL_SECURITY_SIZE];
14585 int index = mono_metadata_declsec_from_index (image, token);
14588 t = &image->tables [MONO_TABLE_DECLSECURITY];
14589 for (i = index; i < t->rows; i++) {
14590 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14592 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14595 /* if present only replace (class) permissions with method permissions */
14596 /* if empty accept either class or method permissions */
14597 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14598 if (!actions->demand.blob) {
14599 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14600 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14601 actions->demand.blob = (char*) (blob + 2);
14602 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14605 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14606 if (!actions->noncasdemand.blob) {
14607 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14608 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14609 actions->noncasdemand.blob = (char*) (blob + 2);
14610 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14613 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14614 if (!actions->demandchoice.blob) {
14615 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14616 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14617 actions->demandchoice.blob = (char*) (blob + 2);
14618 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14628 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14629 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14631 guint32 idx = mono_metadata_token_index (klass->type_token);
14632 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14633 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14634 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14638 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14639 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14641 guint32 idx = mono_method_get_index (method);
14642 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14643 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14644 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14648 * Collect all actions (that requires to generate code in mini) assigned for
14649 * the specified method.
14650 * Note: Don't use the content of actions if the function return FALSE.
14653 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14655 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14656 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14657 MonoBoolean result = FALSE;
14660 /* quick exit if no declarative security is present in the metadata */
14661 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14664 /* we want the original as the wrapper is "free" of the security informations */
14665 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14666 method = mono_marshal_method_from_wrapper (method);
14671 /* First we look for method-level attributes */
14672 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14673 mono_class_init (method->klass);
14674 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14676 result = mono_declsec_get_method_demands_params (method, demands,
14677 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14680 /* Here we use (or create) the class declarative cache to look for demands */
14681 flags = mono_declsec_flags_from_class (method->klass);
14682 if (flags & mask) {
14684 mono_class_init (method->klass);
14685 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14687 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14688 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14691 /* The boolean return value is used as a shortcut in case nothing needs to
14692 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14698 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14700 * Note: Don't use the content of actions if the function return FALSE.
14703 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14705 MonoBoolean result = FALSE;
14708 /* quick exit if no declarative security is present in the metadata */
14709 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14712 /* we want the original as the wrapper is "free" of the security informations */
14713 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14714 method = mono_marshal_method_from_wrapper (method);
14719 /* results are independant - zeroize both */
14720 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14721 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14723 /* First we look for method-level attributes */
14724 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14725 mono_class_init (method->klass);
14727 result = mono_declsec_get_method_demands_params (method, cmethod,
14728 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14731 /* Here we use (or create) the class declarative cache to look for demands */
14732 flags = mono_declsec_flags_from_class (method->klass);
14733 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14734 mono_class_init (method->klass);
14736 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14737 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14744 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14746 * @klass The inherited class - this is the class that provides the security check (attributes)
14748 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14750 * Note: Don't use the content of actions if the function return FALSE.
14753 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14755 MonoBoolean result = FALSE;
14758 /* quick exit if no declarative security is present in the metadata */
14759 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14762 /* Here we use (or create) the class declarative cache to look for demands */
14763 flags = mono_declsec_flags_from_class (klass);
14764 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14765 mono_class_init (klass);
14766 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14768 result |= mono_declsec_get_class_demands_params (klass, demands,
14769 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14776 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14778 * Note: Don't use the content of actions if the function return FALSE.
14781 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14783 /* quick exit if no declarative security is present in the metadata */
14784 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14787 /* we want the original as the wrapper is "free" of the security informations */
14788 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14789 method = mono_marshal_method_from_wrapper (method);
14794 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14795 mono_class_init (method->klass);
14796 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14798 return mono_declsec_get_method_demands_params (method, demands,
14799 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14806 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14808 guint32 cols [MONO_DECL_SECURITY_SIZE];
14812 int index = mono_metadata_declsec_from_index (image, token);
14816 t = &image->tables [MONO_TABLE_DECLSECURITY];
14817 for (i = index; i < t->rows; i++) {
14818 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14820 /* shortcut - index are ordered */
14821 if (token != cols [MONO_DECL_SECURITY_PARENT])
14824 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14825 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14826 entry->blob = (char*) (metadata + 2);
14827 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14836 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14838 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14839 guint32 idx = mono_method_get_index (method);
14840 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14841 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14842 return get_declsec_action (method->klass->image, idx, action, entry);
14848 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14851 guint32 flags = mono_declsec_flags_from_class (klass);
14852 if (declsec_flags_map [action] & flags) {
14853 guint32 idx = mono_metadata_token_index (klass->type_token);
14854 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14855 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14856 return get_declsec_action (klass->image, idx, action, entry);
14862 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14864 guint32 idx = 1; /* there is only one assembly */
14865 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14866 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14868 return get_declsec_action (assembly->image, idx, action, entry);
14872 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14874 MonoObject *res, *exc;
14876 static MonoMethod *method = NULL;
14878 mono_error_init (error);
14880 if (method == NULL) {
14881 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14886 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14887 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14889 g_assert (mono_class_get_ref_info (klass));
14890 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14892 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14893 return_val_if_nok (error, FALSE);
14895 MonoError inner_error;
14896 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14898 if (exc || !is_ok (&inner_error)) {
14899 mono_error_cleanup (&inner_error);
14902 return *(MonoBoolean*)mono_object_unbox (res);
14906 * mono_reflection_type_get_type:
14907 * @reftype: the System.Type object
14909 * Returns the MonoType* associated with the C# System.Type object @reftype.
14912 mono_reflection_type_get_type (MonoReflectionType *reftype)
14914 g_assert (reftype);
14917 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14918 mono_error_assert_ok (&error);
14923 * mono_reflection_assembly_get_assembly:
14924 * @refassembly: the System.Reflection.Assembly object
14926 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14929 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14931 g_assert (refassembly);
14933 return refassembly->assembly;