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 mono_error_init (error);
7642 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7643 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7646 mono_event->klass = klass;
7647 mono_event->event = event;
7648 res = (MonoReflectionEvent*)mono_event;
7649 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7653 * mono_get_reflection_missing_object:
7654 * @domain: Domain where the object lives
7656 * Returns the System.Reflection.Missing.Value singleton object
7657 * (of type System.Reflection.Missing).
7659 * Used as the value for ParameterInfo.DefaultValue when Optional
7663 mono_get_reflection_missing_object (MonoDomain *domain)
7667 static MonoClassField *missing_value_field = NULL;
7669 if (!missing_value_field) {
7670 MonoClass *missing_klass;
7671 missing_klass = mono_class_get_missing_class ();
7672 mono_class_init (missing_klass);
7673 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7674 g_assert (missing_value_field);
7676 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7677 mono_error_assert_ok (&error);
7682 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7685 *dbnull = mono_get_dbnull_object (domain);
7690 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7692 if (!*reflection_missing)
7693 *reflection_missing = mono_get_reflection_missing_object (domain);
7694 return *reflection_missing;
7698 * mono_param_get_objects:
7699 * @domain: an app domain
7702 * Return an System.Reflection.ParameterInfo array object representing the parameters
7703 * in the method @method.
7706 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7708 static MonoClass *System_Reflection_ParameterInfo;
7709 static MonoClass *System_Reflection_ParameterInfo_array;
7710 MonoArray *res = NULL;
7711 MonoReflectionMethod *member = NULL;
7712 MonoReflectionParameter *param = NULL;
7713 char **names = NULL, **blobs = NULL;
7714 guint32 *types = NULL;
7715 MonoType *type = NULL;
7716 MonoObject *dbnull = NULL;
7717 MonoObject *missing = NULL;
7718 MonoMarshalSpec **mspecs = NULL;
7719 MonoMethodSignature *sig = NULL;
7720 MonoVTable *pinfo_vtable;
7721 MonoReflectionType *rt;
7724 mono_error_init (error);
7726 if (!System_Reflection_ParameterInfo_array) {
7729 klass = mono_class_get_mono_parameter_info_class ();
7731 mono_memory_barrier ();
7732 System_Reflection_ParameterInfo = klass;
7735 klass = mono_array_class_get (klass, 1);
7736 mono_memory_barrier ();
7737 System_Reflection_ParameterInfo_array = klass;
7740 sig = mono_method_signature_checked (method, error);
7741 if (!mono_error_ok (error))
7744 if (!sig->param_count) {
7745 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7752 /* Note: the cache is based on the address of the signature into the method
7753 * since we already cache MethodInfos with the method as keys.
7755 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7757 member = mono_method_get_object_checked (domain, method, refclass, error);
7760 names = g_new (char *, sig->param_count);
7761 mono_method_get_param_names (method, (const char **) names);
7763 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7764 mono_method_get_marshal_info (method, mspecs);
7766 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7770 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7771 for (i = 0; i < sig->param_count; ++i) {
7772 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7776 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7780 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7782 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7784 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7786 param->PositionImpl = i;
7787 param->AttrsImpl = sig->params [i]->attrs;
7789 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7790 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7791 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7793 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7797 blobs = g_new0 (char *, sig->param_count);
7798 types = g_new0 (guint32, sig->param_count);
7799 get_default_param_value_blobs (method, blobs, types);
7802 /* Build MonoType for the type from the Constant Table */
7804 type = g_new0 (MonoType, 1);
7805 type->type = (MonoTypeEnum)types [i];
7806 type->data.klass = NULL;
7807 if (types [i] == MONO_TYPE_CLASS)
7808 type->data.klass = mono_defaults.object_class;
7809 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7810 /* For enums, types [i] contains the base type */
7812 type->type = MONO_TYPE_VALUETYPE;
7813 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7815 type->data.klass = mono_class_from_mono_type (type);
7817 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7820 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7822 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7823 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7824 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7825 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7827 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7832 if (mspecs [i + 1]) {
7833 MonoReflectionMarshalAsAttribute* mobj;
7834 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7837 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7840 mono_array_setref (res, i, param);
7850 for (i = sig->param_count; i >= 0; i--) {
7852 mono_metadata_free_marshal_spec (mspecs [i]);
7860 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7864 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7867 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7868 mono_error_assert_ok (&error);
7873 * mono_method_body_get_object:
7874 * @domain: an app domain
7877 * Return an System.Reflection.MethodBody object representing the method @method.
7879 MonoReflectionMethodBody*
7880 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7883 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7884 mono_error_cleanup (&error);
7889 * mono_method_body_get_object_checked:
7890 * @domain: an app domain
7892 * @error: set on error
7894 * Return an System.Reflection.MethodBody object representing the
7895 * method @method. On failure, returns NULL and sets @error.
7897 MonoReflectionMethodBody*
7898 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7900 MonoReflectionMethodBody *ret;
7901 MonoMethodHeader *header;
7903 MonoReflectionType *rt;
7904 guint32 method_rva, local_var_sig_token;
7906 unsigned char format, flags;
7909 mono_error_init (error);
7911 /* for compatibility with .net */
7912 if (method_is_dynamic (method)) {
7913 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7917 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7919 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7920 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7921 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7922 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7923 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7926 image = method->klass->image;
7927 header = mono_method_get_header_checked (method, error);
7928 return_val_if_nok (error, NULL);
7930 if (!image_is_dynamic (image)) {
7931 /* Obtain local vars signature token */
7932 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7933 ptr = mono_image_rva_map (image, method_rva);
7934 flags = *(const unsigned char *) ptr;
7935 format = flags & METHOD_HEADER_FORMAT_MASK;
7937 case METHOD_HEADER_TINY_FORMAT:
7938 local_var_sig_token = 0;
7940 case METHOD_HEADER_FAT_FORMAT:
7944 local_var_sig_token = read32 (ptr);
7947 g_assert_not_reached ();
7950 local_var_sig_token = 0; //FIXME
7952 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7956 ret->init_locals = header->init_locals;
7957 ret->max_stack = header->max_stack;
7958 ret->local_var_sig_token = local_var_sig_token;
7959 MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7962 MONO_OBJECT_SETREF (ret, il, il_arr);
7963 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7966 MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7969 MONO_OBJECT_SETREF (ret, locals, locals_arr);
7970 for (i = 0; i < header->num_locals; ++i) {
7971 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7975 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7979 MONO_OBJECT_SETREF (info, local_type, rt);
7981 info->is_pinned = header->locals [i]->pinned;
7982 info->local_index = i;
7983 mono_array_setref (ret->locals, i, info);
7987 MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7990 MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7991 for (i = 0; i < header->num_clauses; ++i) {
7992 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7995 MonoExceptionClause *clause = &header->clauses [i];
7997 info->flags = clause->flags;
7998 info->try_offset = clause->try_offset;
7999 info->try_length = clause->try_len;
8000 info->handler_offset = clause->handler_offset;
8001 info->handler_length = clause->handler_len;
8002 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8003 info->filter_offset = clause->data.filter_offset;
8004 else if (clause->data.catch_class) {
8005 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
8009 MONO_OBJECT_SETREF (info, catch_type, rt);
8012 mono_array_setref (ret->clauses, i, info);
8015 mono_metadata_free_mh (header);
8016 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
8020 mono_metadata_free_mh (header);
8025 * mono_get_dbnull_object:
8026 * @domain: Domain where the object lives
8028 * Returns the System.DBNull.Value singleton object
8030 * Used as the value for ParameterInfo.DefaultValue
8033 mono_get_dbnull_object (MonoDomain *domain)
8037 static MonoClassField *dbnull_value_field = NULL;
8039 if (!dbnull_value_field) {
8040 MonoClass *dbnull_klass;
8041 dbnull_klass = mono_class_get_dbnull_class ();
8042 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8043 g_assert (dbnull_value_field);
8045 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8046 mono_error_assert_ok (&error);
8051 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8053 guint32 param_index, i, lastp, crow = 0;
8054 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8057 MonoClass *klass = method->klass;
8058 MonoImage *image = klass->image;
8059 MonoMethodSignature *methodsig = mono_method_signature (method);
8061 MonoTableInfo *constt;
8062 MonoTableInfo *methodt;
8063 MonoTableInfo *paramt;
8065 if (!methodsig->param_count)
8068 mono_class_init (klass);
8070 if (image_is_dynamic (klass->image)) {
8071 MonoReflectionMethodAux *aux;
8072 if (method->is_inflated)
8073 method = ((MonoMethodInflated*)method)->declaring;
8074 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8075 if (aux && aux->param_defaults) {
8076 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8077 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8082 methodt = &klass->image->tables [MONO_TABLE_METHOD];
8083 paramt = &klass->image->tables [MONO_TABLE_PARAM];
8084 constt = &image->tables [MONO_TABLE_CONSTANT];
8086 idx = mono_method_get_index (method) - 1;
8087 g_assert (idx != -1);
8089 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8090 if (idx + 1 < methodt->rows)
8091 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8093 lastp = paramt->rows + 1;
8095 for (i = param_index; i < lastp; ++i) {
8098 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8099 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8101 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8104 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8109 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8110 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8111 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8118 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8123 MonoType *basetype = type;
8125 mono_error_init (error);
8130 klass = mono_class_from_mono_type (type);
8131 if (klass->valuetype) {
8132 object = mono_object_new_checked (domain, klass, error);
8133 return_val_if_nok (error, NULL);
8134 retval = ((gchar *) object + sizeof (MonoObject));
8135 if (klass->enumtype)
8136 basetype = mono_class_enum_basetype (klass);
8141 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
8148 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8151 gboolean quoted = FALSE;
8153 memset (assembly, 0, sizeof (MonoAssemblyName));
8154 assembly->culture = "";
8155 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8162 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8173 /* Remove trailing whitespace */
8175 while (*s && g_ascii_isspace (*s))
8178 while (g_ascii_isspace (*p))
8181 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8183 assembly->major = strtoul (p, &s, 10);
8184 if (s == p || *s != '.')
8187 assembly->minor = strtoul (p, &s, 10);
8188 if (s == p || *s != '.')
8191 assembly->build = strtoul (p, &s, 10);
8192 if (s == p || *s != '.')
8195 assembly->revision = strtoul (p, &s, 10);
8199 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8201 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8202 assembly->culture = "";
8205 assembly->culture = p;
8206 while (*p && *p != ',') {
8210 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8212 if (strncmp (p, "null", 4) == 0) {
8217 while (*p && *p != ',') {
8220 len = (p - start + 1);
8221 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8222 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8223 g_strlcpy ((char*)assembly->public_key_token, start, len);
8226 while (*p && *p != ',')
8230 while (g_ascii_isspace (*p) || *p == ',') {
8244 * mono_reflection_parse_type:
8247 * Parse a type name as accepted by the GetType () method and output the info
8248 * extracted in the info structure.
8249 * the name param will be mangled, so, make a copy before passing it to this function.
8250 * The fields in info will be valid until the memory pointed to by name is valid.
8252 * See also mono_type_get_name () below.
8254 * Returns: 0 on parse error.
8257 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8258 MonoTypeNameParse *info)
8260 char *start, *p, *w, *last_point, *startn;
8261 int in_modifiers = 0;
8262 int isbyref = 0, rank = 0, isptr = 0;
8264 start = p = w = name;
8266 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8267 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8268 info->name = info->name_space = NULL;
8269 info->nested = NULL;
8270 info->modifiers = NULL;
8271 info->type_arguments = NULL;
8273 /* last_point separates the namespace from the name */
8276 while (*p == ' ') p++, start++, w++, name++;
8281 *p = 0; /* NULL terminate the name */
8283 info->nested = g_list_append (info->nested, startn);
8284 /* we have parsed the nesting namespace + name */
8288 info->name_space = start;
8290 info->name = last_point + 1;
8292 info->name_space = (char *)"";
8320 info->name_space = start;
8322 info->name = last_point + 1;
8324 info->name_space = (char *)"";
8331 if (isbyref) /* only one level allowed by the spec */
8335 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8339 if (isbyref) /* pointer to ref not okay */
8341 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8346 if (isbyref) /* array of ref and generic ref are not okay */
8348 //Decide if it's an array of a generic argument list
8353 if (*p == ',' || *p == '*' || *p == ']') { //array
8361 else if (*p == '*') /* '*' means unknown lower bound */
8362 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8369 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8371 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8374 info->type_arguments = g_ptr_array_new ();
8376 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8377 gboolean fqname = FALSE;
8379 g_ptr_array_add (info->type_arguments, subinfo);
8381 while (*p == ' ') p++;
8387 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8390 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8391 if (fqname && (*p != ']')) {
8399 while (*p && (*p != ']'))
8407 if (g_ascii_isspace (*aname)) {
8414 !assembly_name_to_aname (&subinfo->assembly, aname))
8416 } else if (fqname && (*p == ']')) {
8438 if (g_ascii_isspace (*p)) {
8445 return 0; /* missing assembly name */
8446 if (!assembly_name_to_aname (&info->assembly, p))
8452 if (info->assembly.name)
8455 // *w = 0; /* terminate class name */
8457 if (!info->name || !*info->name)
8461 /* add other consistency checks */
8467 * mono_identifier_unescape_type_name_chars:
8468 * @identifier: the display name of a mono type
8471 * The name in internal form, that is without escaping backslashes.
8473 * The string is modified in place!
8476 mono_identifier_unescape_type_name_chars(char* identifier)
8481 for (w = r = identifier; *r != 0; r++)
8499 mono_identifier_unescape_info (MonoTypeNameParse* info);
8502 unescape_each_type_argument(void* data, void* user_data)
8504 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8505 mono_identifier_unescape_info (info);
8509 unescape_each_nested_name (void* data, void* user_data)
8511 char* nested_name = (char*) data;
8512 mono_identifier_unescape_type_name_chars(nested_name);
8516 * mono_identifier_unescape_info:
8518 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8522 * Destructively updates the info by unescaping the identifiers that
8523 * comprise the type namespace, name, nested types (if any) and
8524 * generic type arguments (if any).
8526 * The resulting info has the names in internal form.
8530 mono_identifier_unescape_info (MonoTypeNameParse *info)
8534 mono_identifier_unescape_type_name_chars(info->name_space);
8535 mono_identifier_unescape_type_name_chars(info->name);
8536 // but don't escape info->assembly
8537 if (info->type_arguments)
8538 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8540 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8544 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8546 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8548 mono_identifier_unescape_info (info);
8554 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8556 gboolean type_resolve = FALSE;
8558 MonoImage *rootimage = image;
8560 mono_error_init (error);
8562 if (info->assembly.name) {
8563 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8564 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8566 * This could happen in the AOT compiler case when the search hook is not
8569 assembly = image->assembly;
8571 /* then we must load the assembly ourselve - see #60439 */
8572 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8576 image = assembly->image;
8577 } else if (!image) {
8578 image = mono_defaults.corlib;
8581 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8582 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8583 /* ignore the error and try again */
8584 mono_error_cleanup (error);
8585 mono_error_init (error);
8586 image = mono_defaults.corlib;
8587 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8594 * mono_reflection_get_type_internal:
8596 * Returns: may return NULL on success, sets error on failure.
8599 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8604 gboolean bounded = FALSE;
8606 mono_error_init (error);
8608 image = mono_defaults.corlib;
8611 rootimage = mono_defaults.corlib;
8614 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8616 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8621 for (mod = info->nested; mod; mod = mod->next) {
8622 gpointer iter = NULL;
8626 mono_class_init (parent);
8628 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8630 char *nested_name, *nested_nspace;
8631 gboolean match = TRUE;
8633 lastp = strrchr ((const char *)mod->data, '.');
8635 /* Nested classes can have namespaces */
8638 nested_name = g_strdup (lastp + 1);
8639 nspace_len = lastp - (char*)mod->data;
8640 nested_nspace = (char *)g_malloc (nspace_len + 1);
8641 memcpy (nested_nspace, mod->data, nspace_len);
8642 nested_nspace [nspace_len] = '\0';
8645 nested_name = (char *)mod->data;
8646 nested_nspace = NULL;
8649 if (nested_nspace) {
8651 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8654 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8660 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8663 if (strcmp (klass->name, nested_name) != 0)
8668 g_free (nested_name);
8669 g_free (nested_nspace);
8681 if (info->type_arguments) {
8682 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8683 MonoReflectionType *the_type;
8687 for (i = 0; i < info->type_arguments->len; i++) {
8688 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8690 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8691 if (!type_args [i]) {
8697 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8701 instance = mono_reflection_bind_generic_parameters (
8702 the_type, info->type_arguments->len, type_args, error);
8708 klass = mono_class_from_mono_type (instance);
8711 for (mod = info->modifiers; mod; mod = mod->next) {
8712 modval = GPOINTER_TO_UINT (mod->data);
8713 if (!modval) { /* byref: must be last modifier */
8714 return &klass->this_arg;
8715 } else if (modval == -1) {
8716 klass = mono_ptr_class_get (&klass->byval_arg);
8717 } else if (modval == -2) {
8719 } else { /* array rank */
8720 klass = mono_bounded_array_class_get (klass, modval, bounded);
8724 return &klass->byval_arg;
8728 * mono_reflection_get_type:
8729 * @image: a metadata context
8730 * @info: type description structure
8731 * @ignorecase: flag for case-insensitive string compares
8732 * @type_resolve: whenever type resolve was already tried
8734 * Build a MonoType from the type description in @info.
8739 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8741 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8742 mono_error_cleanup (&error);
8747 * mono_reflection_get_type_checked:
8748 * @rootimage: the image of the currently active managed caller
8749 * @image: a metadata context
8750 * @info: type description structure
8751 * @ignorecase: flag for case-insensitive string compares
8752 * @type_resolve: whenever type resolve was already tried
8753 * @error: set on error.
8755 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8759 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8760 mono_error_init (error);
8761 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8766 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8768 MonoReflectionAssemblyBuilder *abuilder;
8772 mono_error_init (error);
8773 g_assert (assembly_is_dynamic (assembly));
8774 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8778 /* Enumerate all modules */
8781 if (abuilder->modules) {
8782 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8783 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8784 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8787 if (!mono_error_ok (error))
8792 if (!type && abuilder->loaded_modules) {
8793 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8794 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8795 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8798 if (!mono_error_ok (error))
8807 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8810 MonoReflectionAssembly *assembly;
8814 mono_error_init (error);
8816 if (image && image_is_dynamic (image))
8817 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8819 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8821 return_val_if_nok (error, NULL);
8825 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8832 *type_resolve = TRUE;
8835 /* Reconstruct the type name */
8836 fullName = g_string_new ("");
8837 if (info->name_space && (info->name_space [0] != '\0'))
8838 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8840 g_string_printf (fullName, "%s", info->name);
8841 for (mod = info->nested; mod; mod = mod->next)
8842 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8844 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8845 if (!is_ok (error)) {
8846 g_string_free (fullName, TRUE);
8851 if (assembly_is_dynamic (assembly->assembly))
8852 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8853 info, ignorecase, error);
8855 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8856 info, ignorecase, error);
8858 g_string_free (fullName, TRUE);
8859 return_val_if_nok (error, NULL);
8864 mono_reflection_free_type_info (MonoTypeNameParse *info)
8866 g_list_free (info->modifiers);
8867 g_list_free (info->nested);
8869 if (info->type_arguments) {
8872 for (i = 0; i < info->type_arguments->len; i++) {
8873 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8875 mono_reflection_free_type_info (subinfo);
8876 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8880 g_ptr_array_free (info->type_arguments, TRUE);
8885 * mono_reflection_type_from_name:
8887 * @image: a metadata context (can be NULL).
8889 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8890 * it defaults to get the type from @image or, if @image is NULL or loading
8891 * from it fails, uses corlib.
8895 mono_reflection_type_from_name (char *name, MonoImage *image)
8898 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8899 mono_error_cleanup (&error);
8904 * mono_reflection_type_from_name_checked:
8906 * @image: a metadata context (can be NULL).
8907 * @error: set on errror.
8909 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8910 * it defaults to get the type from @image or, if @image is NULL or loading
8911 * from it fails, uses corlib. On failure returns NULL and sets @error.
8915 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8917 MonoType *type = NULL;
8918 MonoTypeNameParse info;
8921 mono_error_init (error);
8922 /* Make a copy since parse_type modifies its argument */
8923 tmp = g_strdup (name);
8925 /*g_print ("requested type %s\n", str);*/
8926 if (mono_reflection_parse_type (tmp, &info)) {
8927 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8928 if (!is_ok (error)) {
8930 mono_reflection_free_type_info (&info);
8936 mono_reflection_free_type_info (&info);
8941 * mono_reflection_get_token:
8943 * Return the metadata token of OBJ which should be an object
8944 * representing a metadata element.
8947 mono_reflection_get_token (MonoObject *obj)
8950 guint32 result = mono_reflection_get_token_checked (obj, &error);
8951 mono_error_assert_ok (&error);
8956 * mono_reflection_get_token_checked:
8958 * @error: set on error
8960 * Return the metadata token of @obj which should be an object
8961 * representing a metadata element. On failure sets @error.
8964 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8969 mono_error_init (error);
8971 klass = obj->vtable->klass;
8973 if (strcmp (klass->name, "MethodBuilder") == 0) {
8974 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8976 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8977 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8978 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8980 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8981 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8982 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8984 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8985 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8986 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8987 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8988 } else if (strcmp (klass->name, "RuntimeType") == 0) {
8989 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8990 return_val_if_nok (error, 0);
8991 MonoClass *mc = mono_class_from_mono_type (type);
8992 if (!mono_class_init (mc)) {
8993 mono_error_set_for_class_failure (error, mc);
8997 token = mc->type_token;
8998 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8999 strcmp (klass->name, "MonoMethod") == 0 ||
9000 strcmp (klass->name, "MonoGenericMethod") == 0 ||
9001 strcmp (klass->name, "MonoGenericCMethod") == 0) {
9002 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
9003 if (m->method->is_inflated) {
9004 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
9005 return inflated->declaring->token;
9007 token = m->method->token;
9009 } else if (strcmp (klass->name, "MonoField") == 0) {
9010 MonoReflectionField *f = (MonoReflectionField*)obj;
9012 if (is_field_on_inst (f->field)) {
9013 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
9015 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
9016 int field_index = f->field - dgclass->fields;
9019 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
9020 obj = dgclass->field_objects [field_index];
9021 return mono_reflection_get_token_checked (obj, error);
9024 token = mono_class_get_field_token (f->field);
9025 } else if (strcmp (klass->name, "MonoProperty") == 0) {
9026 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
9028 token = mono_class_get_property_token (p->property);
9029 } else if (strcmp (klass->name, "MonoEvent") == 0) {
9030 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
9032 token = mono_class_get_event_token (p->event);
9033 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
9034 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
9035 MonoClass *member_class = mono_object_class (p->MemberImpl);
9036 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
9038 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
9039 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
9040 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9043 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9044 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9046 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9047 klass->name_space, klass->name);
9055 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
9056 * The @is_enum flag only affects the error message that's displayed on failure.
9059 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9061 MonoError inner_error;
9062 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9064 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9065 "Could not load %s %s while decoding custom attribute: %s",
9066 is_enum ? "enum type": "type",
9068 mono_error_get_message (&inner_error));
9069 mono_error_cleanup (&inner_error);
9076 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9080 int slen = mono_metadata_decode_value (p, &p);
9082 mono_error_init (error);
9084 n = (char *)g_memdup (p, slen + 1);
9086 t = cattr_type_from_name (n, image, TRUE, error);
9088 return_val_if_nok (error, NULL);
9091 return mono_class_from_mono_type (t);
9095 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9097 int slen, type = t->type;
9098 MonoClass *tklass = t->data.klass;
9100 mono_error_init (error);
9106 case MONO_TYPE_BOOLEAN: {
9107 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9112 case MONO_TYPE_CHAR:
9114 case MONO_TYPE_I2: {
9115 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9120 #if SIZEOF_VOID_P == 4
9126 case MONO_TYPE_I4: {
9127 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9132 #if SIZEOF_VOID_P == 8
9133 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9137 case MONO_TYPE_I8: {
9138 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9143 case MONO_TYPE_R8: {
9144 double *val = (double *)g_malloc (sizeof (double));
9149 case MONO_TYPE_VALUETYPE:
9150 if (t->data.klass->enumtype) {
9151 type = mono_class_enum_basetype (t->data.klass)->type;
9154 MonoClass *k = t->data.klass;
9156 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9157 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9163 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9166 case MONO_TYPE_STRING:
9167 if (*p == (char)0xFF) {
9171 slen = mono_metadata_decode_value (p, &p);
9173 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9174 case MONO_TYPE_CLASS: {
9175 MonoReflectionType *rt;
9178 if (*p == (char)0xFF) {
9183 slen = mono_metadata_decode_value (p, &p);
9184 n = (char *)g_memdup (p, slen + 1);
9186 t = cattr_type_from_name (n, image, FALSE, error);
9188 return_val_if_nok (error, NULL);
9191 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9192 if (!mono_error_ok (error))
9197 case MONO_TYPE_OBJECT: {
9200 MonoClass *subc = NULL;
9205 } else if (subt == 0x0E) {
9206 type = MONO_TYPE_STRING;
9208 } else if (subt == 0x1D) {
9209 MonoType simple_type = {{0}};
9213 type = MONO_TYPE_SZARRAY;
9214 if (etype == 0x50) {
9215 tklass = mono_defaults.systemtype_class;
9216 } else if (etype == 0x55) {
9217 tklass = load_cattr_enum_type (image, p, &p, error);
9218 if (!mono_error_ok (error))
9222 /* See Partition II, Appendix B3 */
9223 etype = MONO_TYPE_OBJECT;
9224 simple_type.type = (MonoTypeEnum)etype;
9225 tklass = mono_class_from_mono_type (&simple_type);
9228 } else if (subt == 0x55) {
9231 slen = mono_metadata_decode_value (p, &p);
9232 n = (char *)g_memdup (p, slen + 1);
9234 t = cattr_type_from_name (n, image, FALSE, error);
9236 return_val_if_nok (error, NULL);
9238 subc = mono_class_from_mono_type (t);
9239 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9240 MonoType simple_type = {{0}};
9241 simple_type.type = (MonoTypeEnum)subt;
9242 subc = mono_class_from_mono_type (&simple_type);
9244 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9246 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9248 if (mono_error_ok (error)) {
9249 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9250 g_assert (!subc->has_references);
9251 if (mono_error_ok (error))
9252 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9258 case MONO_TYPE_SZARRAY: {
9260 guint32 i, alen, basetype;
9263 if (alen == 0xffffffff) {
9267 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9268 return_val_if_nok (error, NULL);
9269 basetype = tklass->byval_arg.type;
9270 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9271 basetype = mono_class_enum_basetype (tklass)->type;
9276 case MONO_TYPE_BOOLEAN:
9277 for (i = 0; i < alen; i++) {
9278 MonoBoolean val = *p++;
9279 mono_array_set (arr, MonoBoolean, i, val);
9282 case MONO_TYPE_CHAR:
9285 for (i = 0; i < alen; i++) {
9286 guint16 val = read16 (p);
9287 mono_array_set (arr, guint16, i, val);
9294 for (i = 0; i < alen; i++) {
9295 guint32 val = read32 (p);
9296 mono_array_set (arr, guint32, i, val);
9301 for (i = 0; i < alen; i++) {
9304 mono_array_set (arr, double, i, val);
9310 for (i = 0; i < alen; i++) {
9311 guint64 val = read64 (p);
9312 mono_array_set (arr, guint64, i, val);
9316 case MONO_TYPE_CLASS:
9317 case MONO_TYPE_OBJECT:
9318 case MONO_TYPE_STRING:
9319 case MONO_TYPE_SZARRAY:
9320 for (i = 0; i < alen; i++) {
9321 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9322 if (!mono_error_ok (error))
9324 mono_array_setref (arr, i, item);
9328 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9334 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9340 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9342 mono_error_init (error);
9344 gboolean is_ref = type_is_reference (t);
9346 void *val = load_cattr_value (image, t, p, end, error);
9347 if (!is_ok (error)) {
9354 return (MonoObject*)val;
9356 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9362 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9364 static MonoMethod *ctor;
9366 void *params [2], *unboxed;
9368 mono_error_init (error);
9371 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9373 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9374 return_val_if_nok (error, NULL);
9377 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9378 return_val_if_nok (error, NULL);
9379 unboxed = mono_object_unbox (retval);
9381 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9382 return_val_if_nok (error, NULL);
9388 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9390 static MonoMethod *ctor;
9392 void *unboxed, *params [2];
9394 mono_error_init (error);
9397 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9400 params [1] = typedarg;
9401 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9402 return_val_if_nok (error, NULL);
9404 unboxed = mono_object_unbox (retval);
9406 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9407 return_val_if_nok (error, NULL);
9413 type_is_reference (MonoType *type)
9415 switch (type->type) {
9416 case MONO_TYPE_BOOLEAN:
9417 case MONO_TYPE_CHAR:
9430 case MONO_TYPE_VALUETYPE:
9438 free_param_data (MonoMethodSignature *sig, void **params) {
9440 for (i = 0; i < sig->param_count; ++i) {
9441 if (!type_is_reference (sig->params [i]))
9442 g_free (params [i]);
9447 * Find the field index in the metadata FieldDef table.
9450 find_field_index (MonoClass *klass, MonoClassField *field) {
9453 for (i = 0; i < klass->field.count; ++i) {
9454 if (field == &klass->fields [i])
9455 return klass->field.first + 1 + i;
9461 * Find the property index in the metadata Property table.
9464 find_property_index (MonoClass *klass, MonoProperty *property) {
9467 for (i = 0; i < klass->ext->property.count; ++i) {
9468 if (property == &klass->ext->properties [i])
9469 return klass->ext->property.first + 1 + i;
9475 * Find the event index in the metadata Event table.
9478 find_event_index (MonoClass *klass, MonoEvent *event) {
9481 for (i = 0; i < klass->ext->event.count; ++i) {
9482 if (event == &klass->ext->events [i])
9483 return klass->ext->event.first + 1 + i;
9489 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9491 const char *p = (const char*)data;
9493 guint32 i, j, num_named;
9495 void *params_buf [32];
9496 void **params = NULL;
9497 MonoMethodSignature *sig;
9499 mono_error_init (error);
9501 mono_class_init (method->klass);
9503 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9504 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9509 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9510 if (!mono_error_ok (error)) return NULL;
9512 mono_runtime_invoke_checked (method, attr, NULL, error);
9513 if (!mono_error_ok (error))
9519 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9522 /*g_print ("got attr %s\n", method->klass->name);*/
9524 sig = mono_method_signature (method);
9525 if (sig->param_count < 32) {
9526 params = params_buf;
9527 memset (params, 0, sizeof (void*) * sig->param_count);
9529 /* Allocate using GC so it gets GC tracking */
9530 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9535 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9536 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9537 if (!mono_error_ok (error))
9542 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9543 if (!mono_error_ok (error)) goto fail;
9545 MonoObject *exc = NULL;
9546 mono_runtime_try_invoke (method, attr, params, &exc, error);
9547 if (!mono_error_ok (error))
9550 mono_error_set_exception_instance (error, (MonoException*)exc);
9554 num_named = read16 (named);
9556 for (j = 0; j < num_named; j++) {
9558 char *name, named_type, data_type;
9559 named_type = *named++;
9560 data_type = *named++; /* type of data */
9561 if (data_type == MONO_TYPE_SZARRAY)
9562 data_type = *named++;
9563 if (data_type == MONO_TYPE_ENUM) {
9566 type_len = mono_metadata_decode_blob_size (named, &named);
9567 type_name = (char *)g_malloc (type_len + 1);
9568 memcpy (type_name, named, type_len);
9569 type_name [type_len] = 0;
9571 /* FIXME: lookup the type and check type consistency */
9574 name_len = mono_metadata_decode_blob_size (named, &named);
9575 name = (char *)g_malloc (name_len + 1);
9576 memcpy (name, named, name_len);
9577 name [name_len] = 0;
9579 if (named_type == 0x53) {
9580 MonoClassField *field;
9583 /* how this fail is a blackbox */
9584 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9586 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9591 val = load_cattr_value (image, field->type, named, &named, error);
9592 if (!mono_error_ok (error)) {
9594 if (!type_is_reference (field->type))
9599 mono_field_set_value (attr, field, val);
9600 if (!type_is_reference (field->type))
9602 } else if (named_type == 0x54) {
9605 MonoType *prop_type;
9607 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9610 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9616 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9621 /* can we have more that 1 arg in a custom attr named property? */
9622 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9623 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9625 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9626 if (!mono_error_ok (error)) {
9628 if (!type_is_reference (prop_type))
9629 g_free (pparams [0]);
9634 mono_property_set_value_checked (prop, attr, pparams, error);
9635 if (!type_is_reference (prop_type))
9636 g_free (pparams [0]);
9637 if (!is_ok (error)) {
9645 free_param_data (method->signature, params);
9646 if (params != params_buf)
9647 mono_gc_free_fixed (params);
9652 free_param_data (method->signature, params);
9653 if (params != params_buf)
9654 mono_gc_free_fixed (params);
9659 * mono_reflection_create_custom_attr_data_args:
9661 * Create an array of typed and named arguments from the cattr blob given by DATA.
9662 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9663 * NAMED_ARG_INFO will contain information about the named arguments.
9666 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)
9668 MonoArray *typedargs, *namedargs;
9669 MonoClass *attrklass;
9671 const char *p = (const char*)data;
9673 guint32 i, j, num_named;
9674 CattrNamedArg *arginfo = NULL;
9678 *named_arg_info = NULL;
9680 mono_error_init (error);
9682 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9683 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9687 mono_class_init (method->klass);
9689 domain = mono_domain_get ();
9691 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9694 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9695 return_if_nok (error);
9699 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9702 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9703 return_if_nok (error);
9704 mono_array_setref (typedargs, i, obj);
9708 num_named = read16 (named);
9709 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9710 return_if_nok (error);
9712 attrklass = method->klass;
9714 arginfo = g_new0 (CattrNamedArg, num_named);
9715 *named_arg_info = arginfo;
9717 for (j = 0; j < num_named; j++) {
9719 char *name, named_type, data_type;
9720 named_type = *named++;
9721 data_type = *named++; /* type of data */
9722 if (data_type == MONO_TYPE_SZARRAY)
9723 data_type = *named++;
9724 if (data_type == MONO_TYPE_ENUM) {
9727 type_len = mono_metadata_decode_blob_size (named, &named);
9728 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9731 type_name = (char *)g_malloc (type_len + 1);
9732 memcpy (type_name, named, type_len);
9733 type_name [type_len] = 0;
9735 /* FIXME: lookup the type and check type consistency */
9738 name_len = mono_metadata_decode_blob_size (named, &named);
9739 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9741 name = (char *)g_malloc (name_len + 1);
9742 memcpy (name, named, name_len);
9743 name [name_len] = 0;
9745 if (named_type == 0x53) {
9747 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9754 arginfo [j].type = field->type;
9755 arginfo [j].field = field;
9757 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9758 if (!is_ok (error)) {
9762 mono_array_setref (namedargs, j, obj);
9764 } else if (named_type == 0x54) {
9766 MonoType *prop_type;
9767 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9769 if (!prop || !prop->set) {
9774 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9775 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9777 arginfo [j].type = prop_type;
9778 arginfo [j].prop = prop;
9780 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9781 if (!is_ok (error)) {
9785 mono_array_setref (namedargs, j, obj);
9790 *typed_args = typedargs;
9791 *named_args = namedargs;
9794 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9796 *named_arg_info = NULL;
9800 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9803 MonoArray *typedargs, *namedargs;
9806 CattrNamedArg *arginfo = NULL;
9809 mono_error_init (error);
9817 image = assembly->assembly->image;
9818 method = ref_method->method;
9819 domain = mono_object_domain (ref_method);
9821 if (!mono_class_init (method->klass)) {
9822 mono_error_set_for_class_failure (error, method->klass);
9826 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9830 if (!typedargs || !namedargs)
9833 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9834 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9835 MonoObject *typedarg;
9837 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9840 mono_array_setref (typedargs, i, typedarg);
9843 for (i = 0; i < mono_array_length (namedargs); ++i) {
9844 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9845 MonoObject *typedarg, *namedarg, *minfo;
9847 if (arginfo [i].prop) {
9848 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9852 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9857 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9860 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9864 mono_array_setref (namedargs, i, namedarg);
9867 *ctor_args = typedargs;
9868 *named_args = namedargs;
9872 return mono_error_ok (error);
9876 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9879 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9880 mono_error_set_pending_exception (&error);
9884 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9886 static MonoMethod *ctor;
9892 mono_error_init (error);
9894 g_assert (image->assembly);
9897 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9899 domain = mono_domain_get ();
9900 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9901 return_val_if_nok (error, NULL);
9902 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9903 return_val_if_nok (error, NULL);
9904 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9905 return_val_if_nok (error, NULL);
9906 params [2] = (gpointer)&cattr->data;
9907 params [3] = &cattr->data_size;
9909 mono_runtime_invoke_checked (ctor, attr, params, error);
9910 return_val_if_nok (error, NULL);
9915 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9921 mono_error_init (error);
9924 for (i = 0; i < cinfo->num_attrs; ++i) {
9925 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9929 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9930 return_val_if_nok (error, NULL);
9932 for (i = 0; i < cinfo->num_attrs; ++i) {
9933 if (!cinfo->attrs [i].ctor) {
9934 /* The cattr type is not finished yet */
9935 /* We should include the type name but cinfo doesn't contain it */
9936 mono_error_set_type_load_name (error, NULL, NULL, "");
9939 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9940 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9941 if (!mono_error_ok (error))
9943 mono_array_setref (result, n, attr);
9951 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9954 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9955 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9961 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9967 mono_error_init (error);
9968 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9969 return_val_if_nok (error, NULL);
9970 for (i = 0; i < cinfo->num_attrs; ++i) {
9971 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9972 return_val_if_nok (error, NULL);
9973 mono_array_setref (result, i, attr);
9979 * mono_custom_attrs_from_index:
9981 * Returns: NULL if no attributes are found or if a loading error occurs.
9984 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9987 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9988 mono_error_cleanup (&error);
9992 * mono_custom_attrs_from_index_checked:
9994 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9997 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9999 guint32 mtoken, i, len;
10000 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
10002 MonoCustomAttrInfo *ainfo;
10003 GList *tmp, *list = NULL;
10005 MonoCustomAttrEntry* attr;
10007 mono_error_init (error);
10009 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
10011 i = mono_metadata_custom_attrs_from_index (image, idx);
10015 while (i < ca->rows) {
10016 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
10018 list = g_list_prepend (list, GUINT_TO_POINTER (i));
10021 len = g_list_length (list);
10024 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
10025 ainfo->num_attrs = len;
10026 ainfo->image = image;
10027 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
10028 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
10029 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
10030 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
10031 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
10032 mtoken |= MONO_TOKEN_METHOD_DEF;
10034 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
10035 mtoken |= MONO_TOKEN_MEMBER_REF;
10038 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
10041 attr = &ainfo->attrs [i - 1];
10042 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10044 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10045 g_list_free (list);
10050 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10051 /*FIXME raising an exception here doesn't make any sense*/
10052 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10053 g_list_free (list);
10057 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10058 attr->data_size = mono_metadata_decode_value (data, &data);
10059 attr->data = (guchar*)data;
10061 g_list_free (list);
10066 MonoCustomAttrInfo*
10067 mono_custom_attrs_from_method (MonoMethod *method)
10070 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
10071 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10075 MonoCustomAttrInfo*
10076 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10080 mono_error_init (error);
10083 * An instantiated method has the same cattrs as the generic method definition.
10085 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10086 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10088 if (method->is_inflated)
10089 method = ((MonoMethodInflated *) method)->declaring;
10091 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10092 return lookup_custom_attr (method->klass->image, method);
10094 if (!method->token)
10095 /* Synthetic methods */
10098 idx = mono_method_get_index (method);
10099 idx <<= MONO_CUSTOM_ATTR_BITS;
10100 idx |= MONO_CUSTOM_ATTR_METHODDEF;
10101 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10104 MonoCustomAttrInfo*
10105 mono_custom_attrs_from_class (MonoClass *klass)
10108 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10109 mono_error_cleanup (&error);
10113 MonoCustomAttrInfo*
10114 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10118 mono_error_init (error);
10120 if (klass->generic_class)
10121 klass = klass->generic_class->container_class;
10123 if (image_is_dynamic (klass->image))
10124 return lookup_custom_attr (klass->image, klass);
10126 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10127 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10128 idx <<= MONO_CUSTOM_ATTR_BITS;
10129 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10131 idx = mono_metadata_token_index (klass->type_token);
10132 idx <<= MONO_CUSTOM_ATTR_BITS;
10133 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10135 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10138 MonoCustomAttrInfo*
10139 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10142 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10143 mono_error_cleanup (&error);
10147 MonoCustomAttrInfo*
10148 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10152 mono_error_init (error);
10154 if (image_is_dynamic (assembly->image))
10155 return lookup_custom_attr (assembly->image, assembly);
10156 idx = 1; /* there is only one assembly */
10157 idx <<= MONO_CUSTOM_ATTR_BITS;
10158 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10159 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10162 static MonoCustomAttrInfo*
10163 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10167 if (image_is_dynamic (image))
10168 return lookup_custom_attr (image, image);
10169 idx = 1; /* there is only one module */
10170 idx <<= MONO_CUSTOM_ATTR_BITS;
10171 idx |= MONO_CUSTOM_ATTR_MODULE;
10172 return mono_custom_attrs_from_index_checked (image, idx, error);
10175 MonoCustomAttrInfo*
10176 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10179 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10180 mono_error_cleanup (&error);
10184 MonoCustomAttrInfo*
10185 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10189 if (image_is_dynamic (klass->image)) {
10190 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10191 return lookup_custom_attr (klass->image, property);
10193 idx = find_property_index (klass, property);
10194 idx <<= MONO_CUSTOM_ATTR_BITS;
10195 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10196 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10199 MonoCustomAttrInfo*
10200 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10203 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10204 mono_error_cleanup (&error);
10208 MonoCustomAttrInfo*
10209 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10213 if (image_is_dynamic (klass->image)) {
10214 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10215 return lookup_custom_attr (klass->image, event);
10217 idx = find_event_index (klass, event);
10218 idx <<= MONO_CUSTOM_ATTR_BITS;
10219 idx |= MONO_CUSTOM_ATTR_EVENT;
10220 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10223 MonoCustomAttrInfo*
10224 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10227 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10228 mono_error_cleanup (&error);
10232 MonoCustomAttrInfo*
10233 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10236 mono_error_init (error);
10238 if (image_is_dynamic (klass->image)) {
10239 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10240 return lookup_custom_attr (klass->image, field);
10242 idx = find_field_index (klass, field);
10243 idx <<= MONO_CUSTOM_ATTR_BITS;
10244 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10245 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10249 * mono_custom_attrs_from_param:
10250 * @method: handle to the method that we want to retrieve custom parameter information from
10251 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10253 * The result must be released with mono_custom_attrs_free().
10255 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10257 MonoCustomAttrInfo*
10258 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10261 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10262 mono_error_cleanup (&error);
10267 * mono_custom_attrs_from_param_checked:
10268 * @method: handle to the method that we want to retrieve custom parameter information from
10269 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10270 * @error: set on error
10272 * The result must be released with mono_custom_attrs_free().
10274 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10276 MonoCustomAttrInfo*
10277 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10280 guint32 i, idx, method_index;
10281 guint32 param_list, param_last, param_pos, found;
10283 MonoReflectionMethodAux *aux;
10285 mono_error_init (error);
10288 * An instantiated method has the same cattrs as the generic method definition.
10290 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10291 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10293 if (method->is_inflated)
10294 method = ((MonoMethodInflated *) method)->declaring;
10296 if (image_is_dynamic (method->klass->image)) {
10297 MonoCustomAttrInfo *res, *ainfo;
10300 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10301 if (!aux || !aux->param_cattr)
10304 /* Need to copy since it will be freed later */
10305 ainfo = aux->param_cattr [param];
10308 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10309 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10310 memcpy (res, ainfo, size);
10314 image = method->klass->image;
10315 method_index = mono_method_get_index (method);
10318 ca = &image->tables [MONO_TABLE_METHOD];
10320 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10321 if (method_index == ca->rows) {
10322 ca = &image->tables [MONO_TABLE_PARAM];
10323 param_last = ca->rows + 1;
10325 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10326 ca = &image->tables [MONO_TABLE_PARAM];
10329 for (i = param_list; i < param_last; ++i) {
10330 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10331 if (param_pos == param) {
10339 idx <<= MONO_CUSTOM_ATTR_BITS;
10340 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10341 return mono_custom_attrs_from_index_checked (image, idx, error);
10345 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10349 for (i = 0; i < ainfo->num_attrs; ++i) {
10350 klass = ainfo->attrs [i].ctor->klass;
10351 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10358 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10361 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10362 mono_error_assert_ok (&error); /*FIXME proper error handling*/
10367 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10373 mono_error_init (error);
10376 for (i = 0; i < ainfo->num_attrs; ++i) {
10377 klass = ainfo->attrs [i].ctor->klass;
10378 if (mono_class_has_parent (klass, attr_klass)) {
10383 if (attr_index == -1)
10386 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10387 if (!mono_error_ok (error))
10389 return mono_array_get (attrs, MonoObject*, attr_index);
10393 * mono_reflection_get_custom_attrs_info:
10394 * @obj: a reflection object handle
10396 * Return the custom attribute info for attributes defined for the
10397 * reflection handle @obj. The objects.
10399 * FIXME this function leaks like a sieve for SRE objects.
10401 MonoCustomAttrInfo*
10402 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10405 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10406 mono_error_assert_ok (&error);
10411 * mono_reflection_get_custom_attrs_info_checked:
10412 * @obj: a reflection object handle
10413 * @error: set on error
10415 * Return the custom attribute info for attributes defined for the
10416 * reflection handle @obj. The objects.
10418 * On failure returns NULL and sets @error.
10420 * FIXME this function leaks like a sieve for SRE objects.
10422 MonoCustomAttrInfo*
10423 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10426 MonoCustomAttrInfo *cinfo = NULL;
10428 mono_error_init (error);
10430 klass = obj->vtable->klass;
10431 if (klass == mono_defaults.runtimetype_class) {
10432 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10433 return_val_if_nok (error, NULL);
10434 klass = mono_class_from_mono_type (type);
10435 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10436 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10437 return_val_if_nok (error, NULL);
10438 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10439 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10440 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10441 return_val_if_nok (error, NULL);
10442 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10443 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10444 cinfo = mono_custom_attrs_from_module (module->image, error);
10445 return_val_if_nok (error, NULL);
10446 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10447 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10448 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10449 return_val_if_nok (error, NULL);
10450 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10451 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10452 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10453 return_val_if_nok (error, NULL);
10454 } else if (strcmp ("MonoField", klass->name) == 0) {
10455 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10456 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10457 return_val_if_nok (error, NULL);
10458 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10459 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10460 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10461 return_val_if_nok (error, NULL);
10462 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10463 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10464 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10465 return_val_if_nok (error, NULL);
10466 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10467 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10468 MonoClass *member_class = mono_object_class (param->MemberImpl);
10469 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10470 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10471 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10472 return_val_if_nok (error, NULL);
10473 } else if (is_sr_mono_property (member_class)) {
10474 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10475 MonoMethod *method;
10476 if (!(method = prop->property->get))
10477 method = prop->property->set;
10480 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10481 return_val_if_nok (error, NULL);
10483 #ifndef DISABLE_REFLECTION_EMIT
10484 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10485 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10486 return_val_if_nok (error, NULL);
10487 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10488 return_val_if_nok (error, NULL);
10489 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10490 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10491 MonoMethod *method = NULL;
10492 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10493 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10494 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10495 method = ((MonoReflectionMethod *)c->cb)->method;
10497 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));
10499 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10500 return_val_if_nok (error, NULL);
10504 char *type_name = mono_type_get_full_name (member_class);
10505 mono_error_set_not_supported (error,
10506 "Custom attributes on a ParamInfo with member %s are not supported",
10508 g_free (type_name);
10511 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10512 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10513 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10514 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10515 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10516 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10517 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10518 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10519 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10520 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10521 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10522 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10523 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10524 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10525 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10526 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10527 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10528 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10529 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10530 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10531 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10532 return_val_if_nok (error, NULL);
10533 } else { /* handle other types here... */
10534 g_error ("get custom attrs not yet supported for %s", klass->name);
10541 * mono_reflection_get_custom_attrs_by_type:
10542 * @obj: a reflection object handle
10544 * Return an array with all the custom attributes defined of the
10545 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10546 * of that type are returned. The objects are fully build. Return NULL if a loading error
10550 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10553 MonoCustomAttrInfo *cinfo;
10555 mono_error_init (error);
10557 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10558 return_val_if_nok (error, NULL);
10560 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10561 if (!cinfo->cached)
10562 mono_custom_attrs_free (cinfo);
10566 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10573 * mono_reflection_get_custom_attrs:
10574 * @obj: a reflection object handle
10576 * Return an array with all the custom attributes defined of the
10577 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10581 mono_reflection_get_custom_attrs (MonoObject *obj)
10585 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10589 * mono_reflection_get_custom_attrs_data:
10590 * @obj: a reflection obj handle
10592 * Returns an array of System.Reflection.CustomAttributeData,
10593 * which include information about attributes reflected on
10594 * types loaded using the Reflection Only methods
10597 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10601 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10602 mono_error_cleanup (&error);
10607 * mono_reflection_get_custom_attrs_data_checked:
10608 * @obj: a reflection obj handle
10609 * @error: set on error
10611 * Returns an array of System.Reflection.CustomAttributeData,
10612 * which include information about attributes reflected on
10613 * types loaded using the Reflection Only methods
10616 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10619 MonoCustomAttrInfo *cinfo;
10621 mono_error_init (error);
10623 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10624 return_val_if_nok (error, NULL);
10626 result = mono_custom_attrs_data_construct (cinfo, error);
10627 if (!cinfo->cached)
10628 mono_custom_attrs_free (cinfo);
10629 return_val_if_nok (error, NULL);
10631 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10636 static MonoReflectionType*
10637 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10639 static MonoMethod *method_get_underlying_system_type = NULL;
10640 MonoReflectionType *rt;
10641 MonoMethod *usertype_method;
10643 mono_error_init (error);
10645 if (!method_get_underlying_system_type)
10646 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10648 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10650 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10657 is_corlib_type (MonoClass *klass)
10659 return klass->image == mono_defaults.corlib;
10662 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10663 static MonoClass *cached_class; \
10664 if (cached_class) \
10665 return cached_class == _class; \
10666 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10667 cached_class = _class; \
10674 #ifndef DISABLE_REFLECTION_EMIT
10676 is_sre_array (MonoClass *klass)
10678 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10682 is_sre_byref (MonoClass *klass)
10684 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10688 is_sre_pointer (MonoClass *klass)
10690 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10694 is_sre_generic_instance (MonoClass *klass)
10696 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10700 is_sre_type_builder (MonoClass *klass)
10702 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10706 is_sre_method_builder (MonoClass *klass)
10708 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10712 is_sre_ctor_builder (MonoClass *klass)
10714 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10718 is_sre_field_builder (MonoClass *klass)
10720 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10724 is_sre_method_on_tb_inst (MonoClass *klass)
10726 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10730 is_sre_ctor_on_tb_inst (MonoClass *klass)
10732 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10736 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10739 mono_error_init (error);
10746 if (is_usertype (ref)) {
10747 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10748 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10754 klass = mono_object_class (ref);
10756 if (is_sre_array (klass)) {
10758 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10759 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10760 return_val_if_nok (error, NULL);
10762 if (sre_array->rank == 0) //single dimentional array
10763 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10765 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10766 sre_array->type.type = res;
10768 } else if (is_sre_byref (klass)) {
10770 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10771 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10772 return_val_if_nok (error, NULL);
10774 res = &mono_class_from_mono_type (base)->this_arg;
10775 sre_byref->type.type = res;
10777 } else if (is_sre_pointer (klass)) {
10779 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10780 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10781 return_val_if_nok (error, NULL);
10783 res = &mono_ptr_class_get (base)->byval_arg;
10784 sre_pointer->type.type = res;
10786 } else if (is_sre_generic_instance (klass)) {
10787 MonoType *res, **types;
10788 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10791 count = mono_array_length (gclass->type_arguments);
10792 types = g_new0 (MonoType*, count);
10793 for (i = 0; i < count; ++i) {
10794 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10795 types [i] = mono_reflection_type_get_handle (t, error);
10796 if (!types[i] || !is_ok (error)) {
10802 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10805 gclass->type.type = res;
10809 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10814 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10817 mono_reflection_type_get_handle (type, &error);
10818 mono_error_set_pending_exception (&error);
10822 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10824 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10827 mono_error_init (error);
10829 MonoType *res = mono_reflection_type_get_handle (type, error);
10831 if (!res && is_ok (error)) {
10832 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10834 return_val_if_nok (error, FALSE);
10836 klass = mono_class_from_mono_type (res);
10838 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10839 mono_domain_lock (domain);
10841 if (!image_is_dynamic (klass->image)) {
10842 mono_class_setup_supertypes (klass);
10844 if (!domain->type_hash)
10845 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10846 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10847 mono_g_hash_table_insert (domain->type_hash, res, type);
10849 mono_domain_unlock (domain);
10850 mono_loader_unlock ();
10856 mono_reflection_register_with_runtime (MonoReflectionType *type)
10859 (void) reflection_register_with_runtime (type, &error);
10860 mono_error_set_pending_exception (&error);
10864 * LOCKING: Assumes the loader lock is held.
10866 static MonoMethodSignature*
10867 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10868 MonoMethodSignature *sig;
10871 mono_error_init (error);
10873 count = parameters? mono_array_length (parameters): 0;
10875 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10876 sig->param_count = count;
10877 sig->sentinelpos = -1; /* FIXME */
10878 for (i = 0; i < count; ++i) {
10879 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10880 if (!is_ok (error)) {
10881 image_g_free (image, sig);
10889 * LOCKING: Assumes the loader lock is held.
10891 static MonoMethodSignature*
10892 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10893 MonoMethodSignature *sig;
10895 mono_error_init (error);
10897 sig = parameters_to_signature (image, ctor->parameters, error);
10898 return_val_if_nok (error, NULL);
10899 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10900 sig->ret = &mono_defaults.void_class->byval_arg;
10905 * LOCKING: Assumes the loader lock is held.
10907 static MonoMethodSignature*
10908 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10909 MonoMethodSignature *sig;
10911 mono_error_init (error);
10913 sig = parameters_to_signature (image, method->parameters, error);
10914 return_val_if_nok (error, NULL);
10915 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10916 if (method->rtype) {
10917 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10918 if (!is_ok (error)) {
10919 image_g_free (image, sig);
10923 sig->ret = &mono_defaults.void_class->byval_arg;
10925 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10929 static MonoMethodSignature*
10930 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10931 MonoMethodSignature *sig;
10933 mono_error_init (error);
10935 sig = parameters_to_signature (NULL, method->parameters, error);
10936 return_val_if_nok (error, NULL);
10937 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10938 if (method->rtype) {
10939 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10940 if (!is_ok (error)) {
10945 sig->ret = &mono_defaults.void_class->byval_arg;
10947 sig->generic_param_count = 0;
10952 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10954 mono_error_init (error);
10955 MonoClass *klass = mono_object_class (prop);
10956 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10957 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10958 *name = mono_string_to_utf8_checked (pb->name, error);
10959 return_if_nok (error);
10960 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10962 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10963 *name = g_strdup (p->property->name);
10964 if (p->property->get)
10965 *type = mono_method_signature (p->property->get)->ret;
10967 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10972 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10974 mono_error_init (error);
10975 MonoClass *klass = mono_object_class (field);
10976 if (strcmp (klass->name, "FieldBuilder") == 0) {
10977 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10978 *name = mono_string_to_utf8_checked (fb->name, error);
10979 return_if_nok (error);
10980 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10982 MonoReflectionField *f = (MonoReflectionField *)field;
10983 *name = g_strdup (mono_field_get_name (f->field));
10984 *type = f->field->type;
10988 #else /* DISABLE_REFLECTION_EMIT */
10991 mono_reflection_register_with_runtime (MonoReflectionType *type)
10993 /* This is empty */
10997 is_sre_type_builder (MonoClass *klass)
11003 is_sre_generic_instance (MonoClass *klass)
11009 init_type_builder_generics (MonoObject *type, MonoError *error)
11011 mono_error_init (error);
11014 #endif /* !DISABLE_REFLECTION_EMIT */
11018 is_sr_mono_field (MonoClass *klass)
11020 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
11024 is_sr_mono_property (MonoClass *klass)
11026 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
11030 is_sr_mono_method (MonoClass *klass)
11032 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
11036 is_sr_mono_cmethod (MonoClass *klass)
11038 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
11042 is_sr_mono_generic_method (MonoClass *klass)
11044 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11048 is_sr_mono_generic_cmethod (MonoClass *klass)
11050 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11054 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11056 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11060 is_usertype (MonoReflectionType *ref)
11062 MonoClass *klass = mono_object_class (ref);
11063 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11066 static MonoReflectionType*
11067 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11069 mono_error_init (error);
11070 if (!type || type->type)
11073 if (is_usertype (type)) {
11074 type = mono_reflection_type_get_underlying_system_type (type, error);
11075 return_val_if_nok (error, NULL);
11076 if (is_usertype (type)) {
11077 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11085 * encode_cattr_value:
11086 * Encode a value in a custom attribute stream of bytes.
11087 * The value to encode is either supplied as an object in argument val
11088 * (valuetypes are boxed), or as a pointer to the data in the
11090 * @type represents the type of the value
11091 * @buffer is the start of the buffer
11092 * @p the current position in the buffer
11093 * @buflen contains the size of the buffer and is used to return the new buffer size
11094 * if this needs to be realloced.
11095 * @retbuffer and @retp return the start and the position of the buffer
11096 * @error set on error.
11099 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11101 MonoTypeEnum simple_type;
11103 mono_error_init (error);
11104 if ((p-buffer) + 10 >= *buflen) {
11107 newbuf = (char *)g_realloc (buffer, *buflen);
11108 p = newbuf + (p-buffer);
11112 argval = ((char*)arg + sizeof (MonoObject));
11113 simple_type = type->type;
11115 switch (simple_type) {
11116 case MONO_TYPE_BOOLEAN:
11121 case MONO_TYPE_CHAR:
11124 swap_with_size (p, argval, 2, 1);
11130 swap_with_size (p, argval, 4, 1);
11134 swap_with_size (p, argval, 8, 1);
11139 swap_with_size (p, argval, 8, 1);
11142 case MONO_TYPE_VALUETYPE:
11143 if (type->data.klass->enumtype) {
11144 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11147 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11150 case MONO_TYPE_STRING: {
11157 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11158 return_if_nok (error);
11159 slen = strlen (str);
11160 if ((p-buffer) + 10 + slen >= *buflen) {
11164 newbuf = (char *)g_realloc (buffer, *buflen);
11165 p = newbuf + (p-buffer);
11168 mono_metadata_encode_value (slen, p, &p);
11169 memcpy (p, str, slen);
11174 case MONO_TYPE_CLASS: {
11177 MonoType *arg_type;
11183 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11184 return_if_nok (error);
11186 str = type_get_qualified_name (arg_type, NULL);
11187 slen = strlen (str);
11188 if ((p-buffer) + 10 + slen >= *buflen) {
11192 newbuf = (char *)g_realloc (buffer, *buflen);
11193 p = newbuf + (p-buffer);
11196 mono_metadata_encode_value (slen, p, &p);
11197 memcpy (p, str, slen);
11202 case MONO_TYPE_SZARRAY: {
11204 MonoClass *eclass, *arg_eclass;
11207 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11210 len = mono_array_length ((MonoArray*)arg);
11212 *p++ = (len >> 8) & 0xff;
11213 *p++ = (len >> 16) & 0xff;
11214 *p++ = (len >> 24) & 0xff;
11216 *retbuffer = buffer;
11217 eclass = type->data.klass;
11218 arg_eclass = mono_object_class (arg)->element_class;
11221 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11222 eclass = mono_defaults.object_class;
11224 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11225 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11226 int elsize = mono_class_array_element_size (arg_eclass);
11227 for (i = 0; i < len; ++i) {
11228 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11229 return_if_nok (error);
11232 } else if (eclass->valuetype && arg_eclass->valuetype) {
11233 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11234 int elsize = mono_class_array_element_size (eclass);
11235 for (i = 0; i < len; ++i) {
11236 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11237 return_if_nok (error);
11241 for (i = 0; i < len; ++i) {
11242 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11243 return_if_nok (error);
11248 case MONO_TYPE_OBJECT: {
11254 * The parameter type is 'object' but the type of the actual
11255 * argument is not. So we have to add type information to the blob
11256 * too. This is completely undocumented in the spec.
11260 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11265 klass = mono_object_class (arg);
11267 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11271 return_if_nok (error);
11274 if (klass->enumtype) {
11276 } else if (klass == mono_defaults.string_class) {
11277 simple_type = MONO_TYPE_STRING;
11280 } else if (klass->rank == 1) {
11282 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11283 /* See Partition II, Appendix B3 */
11286 *p++ = klass->element_class->byval_arg.type;
11287 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11288 return_if_nok (error);
11290 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11291 *p++ = simple_type = klass->byval_arg.type;
11294 g_error ("unhandled type in custom attr");
11296 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11297 slen = strlen (str);
11298 if ((p-buffer) + 10 + slen >= *buflen) {
11302 newbuf = (char *)g_realloc (buffer, *buflen);
11303 p = newbuf + (p-buffer);
11306 mono_metadata_encode_value (slen, p, &p);
11307 memcpy (p, str, slen);
11310 simple_type = mono_class_enum_basetype (klass)->type;
11314 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11317 *retbuffer = buffer;
11321 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11323 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11324 char *str = type_get_qualified_name (type, NULL);
11325 int slen = strlen (str);
11329 * This seems to be optional...
11332 mono_metadata_encode_value (slen, p, &p);
11333 memcpy (p, str, slen);
11336 } else if (type->type == MONO_TYPE_OBJECT) {
11338 } else if (type->type == MONO_TYPE_CLASS) {
11339 /* it should be a type: encode_cattr_value () has the check */
11342 mono_metadata_encode_value (type->type, p, &p);
11343 if (type->type == MONO_TYPE_SZARRAY)
11344 /* See the examples in Partition VI, Annex B */
11345 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11351 #ifndef DISABLE_REFLECTION_EMIT
11353 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11357 mono_error_init (error);
11359 /* Preallocate a large enough buffer */
11360 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11361 char *str = type_get_qualified_name (type, NULL);
11362 len = strlen (str);
11364 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11365 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11366 len = strlen (str);
11371 len += strlen (name);
11373 if ((p-buffer) + 20 + len >= *buflen) {
11377 newbuf = (char *)g_realloc (buffer, *buflen);
11378 p = newbuf + (p-buffer);
11382 encode_field_or_prop_type (type, p, &p);
11384 len = strlen (name);
11385 mono_metadata_encode_value (len, p, &p);
11386 memcpy (p, name, len);
11388 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11389 return_if_nok (error);
11391 *retbuffer = buffer;
11395 * mono_reflection_get_custom_attrs_blob:
11396 * @ctor: custom attribute constructor
11397 * @ctorArgs: arguments o the constructor
11403 * Creates the blob of data that needs to be saved in the metadata and that represents
11404 * the custom attributed described by @ctor, @ctorArgs etc.
11405 * Returns: a Byte array representing the blob of data.
11408 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11411 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11412 mono_error_cleanup (&error);
11417 * mono_reflection_get_custom_attrs_blob_checked:
11418 * @ctor: custom attribute constructor
11419 * @ctorArgs: arguments o the constructor
11424 * @error: set on error
11426 * Creates the blob of data that needs to be saved in the metadata and that represents
11427 * the custom attributed described by @ctor, @ctorArgs etc.
11428 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11431 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11433 MonoArray *result = NULL;
11434 MonoMethodSignature *sig;
11439 mono_error_init (error);
11441 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11442 /* sig is freed later so allocate it in the heap */
11443 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11444 if (!is_ok (error)) {
11449 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11452 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11454 p = buffer = (char *)g_malloc (buflen);
11455 /* write the prolog */
11458 for (i = 0; i < sig->param_count; ++i) {
11459 arg = mono_array_get (ctorArgs, MonoObject*, i);
11460 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11461 if (!is_ok (error)) goto leave;
11465 i += mono_array_length (properties);
11467 i += mono_array_length (fields);
11469 *p++ = (i >> 8) & 0xff;
11472 for (i = 0; i < mono_array_length (properties); ++i) {
11476 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11477 get_prop_name_and_type (prop, &pname, &ptype, error);
11478 if (!is_ok (error)) goto leave;
11479 *p++ = 0x54; /* PROPERTY signature */
11480 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11482 if (!is_ok (error)) goto leave;
11488 for (i = 0; i < mono_array_length (fields); ++i) {
11492 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11493 get_field_name_and_type (field, &fname, &ftype, error);
11494 if (!is_ok (error)) goto leave;
11495 *p++ = 0x53; /* FIELD signature */
11496 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11498 if (!is_ok (error)) goto leave;
11502 g_assert (p - buffer <= buflen);
11503 buflen = p - buffer;
11504 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11505 if (!is_ok (error))
11507 p = mono_array_addr (result, char, 0);
11508 memcpy (p, buffer, buflen);
11511 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11517 * reflection_setup_internal_class:
11518 * @tb: a TypeBuilder object
11519 * @error: set on error
11521 * Creates a MonoClass that represents the TypeBuilder.
11522 * This is a trick that lets us simplify a lot of reflection code
11523 * (and will allow us to support Build and Run assemblies easier).
11525 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11528 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11530 MonoClass *klass, *parent;
11532 mono_error_init (error);
11533 RESOLVE_TYPE (tb->parent, error);
11534 return_val_if_nok (error, FALSE);
11536 mono_loader_lock ();
11539 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11540 if (!is_ok (error)) {
11541 mono_loader_unlock ();
11544 /* check so we can compile corlib correctly */
11545 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11546 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11547 parent = parent_type->data.klass;
11549 parent = mono_class_from_mono_type (parent_type);
11555 /* the type has already being created: it means we just have to change the parent */
11556 if (tb->type.type) {
11557 klass = mono_class_from_mono_type (tb->type.type);
11558 klass->parent = NULL;
11559 /* fool mono_class_setup_parent */
11560 klass->supertypes = NULL;
11561 mono_class_setup_parent (klass, parent);
11562 mono_class_setup_mono_type (klass);
11563 mono_loader_unlock ();
11567 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11569 klass->image = &tb->module->dynamic_image->image;
11571 klass->inited = 1; /* we lie to the runtime */
11572 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11573 if (!is_ok (error))
11575 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11576 if (!is_ok (error))
11578 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11579 klass->flags = tb->attrs;
11581 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11583 klass->element_class = klass;
11585 if (mono_class_get_ref_info (klass) == NULL) {
11587 mono_class_set_ref_info (klass, tb);
11589 /* Put into cache so mono_class_get_checked () will find it.
11590 Skip nested types as those should not be available on the global scope. */
11591 if (!tb->nesting_type)
11592 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11595 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11596 by performing a mono_class_get which does the full resolution.
11598 Working around this semantics would require us to write a lot of code for no clear advantage.
11600 mono_image_append_class_to_reflection_info_set (klass);
11602 g_assert (mono_class_get_ref_info (klass) == tb);
11605 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11607 if (parent != NULL) {
11608 mono_class_setup_parent (klass, parent);
11609 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11610 const char *old_n = klass->name;
11611 /* trick to get relative numbering right when compiling corlib */
11612 klass->name = "BuildingObject";
11613 mono_class_setup_parent (klass, mono_defaults.object_class);
11614 klass->name = old_n;
11617 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11618 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11619 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11620 klass->instance_size = sizeof (MonoObject);
11621 klass->size_inited = 1;
11622 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11625 mono_class_setup_mono_type (klass);
11627 mono_class_setup_supertypes (klass);
11630 * FIXME: handle interfaces.
11633 tb->type.type = &klass->byval_arg;
11635 if (tb->nesting_type) {
11636 g_assert (tb->nesting_type->type);
11637 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11638 if (!is_ok (error)) goto failure;
11639 klass->nested_in = mono_class_from_mono_type (nesting_type);
11642 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11644 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11646 mono_loader_unlock ();
11650 mono_loader_unlock ();
11655 * mono_reflection_setup_internal_class:
11656 * @tb: a TypeBuilder object
11659 * Creates a MonoClass that represents the TypeBuilder.
11660 * This is a trick that lets us simplify a lot of reflection code
11661 * (and will allow us to support Build and Run assemblies easier).
11665 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11668 (void) reflection_setup_internal_class (tb, &error);
11669 mono_error_set_pending_exception (&error);
11673 * mono_reflection_setup_generic_class:
11674 * @tb: a TypeBuilder object
11676 * Setup the generic class before adding the first generic parameter.
11679 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11684 * mono_reflection_create_generic_class:
11685 * @tb: a TypeBuilder object
11686 * @error: set on error
11688 * Creates the generic class after all generic parameters have been added.
11689 * On success returns TRUE, on failure returns FALSE and sets @error.
11693 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11699 mono_error_init (error);
11701 klass = mono_class_from_mono_type (tb->type.type);
11703 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11705 if (klass->generic_container || (count == 0))
11708 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11710 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11712 klass->generic_container->owner.klass = klass;
11713 klass->generic_container->type_argc = count;
11714 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11716 klass->is_generic = 1;
11718 for (i = 0; i < count; i++) {
11719 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11720 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11721 return_val_if_nok (error, FALSE);
11722 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11723 klass->generic_container->type_params [i] = *param;
11724 /*Make sure we are a diferent type instance */
11725 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11726 klass->generic_container->type_params [i].info.pklass = NULL;
11727 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11729 g_assert (klass->generic_container->type_params [i].param.owner);
11732 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11737 * reflection_create_internal_class:
11738 * @tb: a TypeBuilder object
11739 * @error: set on error
11741 * Actually create the MonoClass that is associated with the TypeBuilder.
11742 * On success returns TRUE, on failure returns FALSE and sets @error.
11746 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11751 mono_error_init (error);
11752 klass = mono_class_from_mono_type (tb->type.type);
11754 mono_loader_lock ();
11755 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11756 MonoReflectionFieldBuilder *fb;
11758 MonoType *enum_basetype;
11760 g_assert (tb->fields != NULL);
11761 g_assert (mono_array_length (tb->fields) >= 1);
11763 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11765 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11766 if (!is_ok (error)) {
11767 mono_loader_unlock ();
11770 if (!mono_type_is_valid_enum_basetype (field_type)) {
11771 mono_loader_unlock ();
11775 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11776 if (!is_ok (error)) {
11777 mono_loader_unlock ();
11780 klass->element_class = mono_class_from_mono_type (enum_basetype);
11781 if (!klass->element_class)
11782 klass->element_class = mono_class_from_mono_type (enum_basetype);
11785 * get the element_class from the current corlib.
11787 ec = default_class_from_mono_type (enum_basetype);
11788 klass->instance_size = ec->instance_size;
11789 klass->size_inited = 1;
11791 * this is almost safe to do with enums and it's needed to be able
11792 * to create objects of the enum type (for use in SetConstant).
11794 /* FIXME: Does this mean enums can't have method overrides ? */
11795 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11797 mono_loader_unlock ();
11802 * mono_reflection_create_internal_class:
11803 * @tb: a TypeBuilder object
11806 * Actually create the MonoClass that is associated with the TypeBuilder.
11809 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11812 (void) reflection_create_internal_class (tb, &error);
11813 mono_error_set_pending_exception (&error);
11816 static MonoMarshalSpec*
11817 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11818 MonoReflectionMarshal *minfo, MonoError *error)
11820 MonoMarshalSpec *res;
11822 mono_error_init (error);
11824 res = image_g_new0 (image, MonoMarshalSpec, 1);
11825 res->native = (MonoMarshalNative)minfo->type;
11827 switch (minfo->type) {
11828 case MONO_NATIVE_LPARRAY:
11829 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11830 if (minfo->has_size) {
11831 res->data.array_data.param_num = minfo->param_num;
11832 res->data.array_data.num_elem = minfo->count;
11833 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11836 res->data.array_data.param_num = -1;
11837 res->data.array_data.num_elem = -1;
11838 res->data.array_data.elem_mult = -1;
11842 case MONO_NATIVE_BYVALTSTR:
11843 case MONO_NATIVE_BYVALARRAY:
11844 res->data.array_data.num_elem = minfo->count;
11847 case MONO_NATIVE_CUSTOM:
11848 if (minfo->marshaltyperef) {
11849 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11850 if (!is_ok (error)) {
11851 image_g_free (image, res);
11854 res->data.custom_data.custom_name =
11855 type_get_fully_qualified_name (marshaltyperef);
11857 if (minfo->mcookie) {
11858 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11859 if (!is_ok (error)) {
11860 image_g_free (image, res);
11872 #endif /* !DISABLE_REFLECTION_EMIT */
11874 MonoReflectionMarshalAsAttribute*
11875 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11876 MonoMarshalSpec *spec, MonoError *error)
11878 MonoReflectionType *rt;
11879 MonoReflectionMarshalAsAttribute *minfo;
11882 mono_error_init (error);
11884 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11887 minfo->utype = spec->native;
11889 switch (minfo->utype) {
11890 case MONO_NATIVE_LPARRAY:
11891 minfo->array_subtype = spec->data.array_data.elem_type;
11892 minfo->size_const = spec->data.array_data.num_elem;
11893 if (spec->data.array_data.param_num != -1)
11894 minfo->size_param_index = spec->data.array_data.param_num;
11897 case MONO_NATIVE_BYVALTSTR:
11898 case MONO_NATIVE_BYVALARRAY:
11899 minfo->size_const = spec->data.array_data.num_elem;
11902 case MONO_NATIVE_CUSTOM:
11903 if (spec->data.custom_data.custom_name) {
11904 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11905 return_val_if_nok (error, NULL);
11908 rt = mono_type_get_object_checked (domain, mtype, error);
11912 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11915 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11917 if (spec->data.custom_data.cookie)
11918 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11928 #ifndef DISABLE_REFLECTION_EMIT
11930 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11931 ReflectionMethodBuilder *rmb,
11932 MonoMethodSignature *sig,
11936 MonoMethodWrapper *wrapperm;
11937 MonoMarshalSpec **specs;
11938 MonoReflectionMethodAux *method_aux;
11943 mono_error_init (error);
11945 * Methods created using a MethodBuilder should have their memory allocated
11946 * inside the image mempool, while dynamic methods should have their memory
11949 dynamic = rmb->refs != NULL;
11950 image = dynamic ? NULL : klass->image;
11953 g_assert (!klass->generic_class);
11955 mono_loader_lock ();
11957 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11958 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11959 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11961 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11963 wrapperm = (MonoMethodWrapper*)m;
11965 m->dynamic = dynamic;
11967 m->flags = rmb->attrs;
11968 m->iflags = rmb->iattrs;
11969 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11971 m->signature = sig;
11972 m->sre_method = TRUE;
11973 m->skip_visibility = rmb->skip_visibility;
11974 if (rmb->table_idx)
11975 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11977 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11978 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11979 m->string_ctor = 1;
11981 m->signature->pinvoke = 1;
11982 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11983 m->signature->pinvoke = 1;
11985 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11987 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11988 mono_error_assert_ok (error);
11989 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11990 mono_error_assert_ok (error);
11992 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11994 if (image_is_dynamic (klass->image))
11995 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11997 mono_loader_unlock ();
12000 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
12001 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
12002 MonoMethodHeader *header;
12004 gint32 max_stack, i;
12005 gint32 num_locals = 0;
12006 gint32 num_clauses = 0;
12010 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
12011 code_size = rmb->ilgen->code_len;
12012 max_stack = rmb->ilgen->max_stack;
12013 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
12014 if (rmb->ilgen->ex_handlers)
12015 num_clauses = method_count_clauses (rmb->ilgen);
12018 code = mono_array_addr (rmb->code, guint8, 0);
12019 code_size = mono_array_length (rmb->code);
12020 /* we probably need to run a verifier on the code... */
12030 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
12031 header->code_size = code_size;
12032 header->code = (const unsigned char *)image_g_malloc (image, code_size);
12033 memcpy ((char*)header->code, code, code_size);
12034 header->max_stack = max_stack;
12035 header->init_locals = rmb->init_locals;
12036 header->num_locals = num_locals;
12038 for (i = 0; i < num_locals; ++i) {
12039 MonoReflectionLocalBuilder *lb =
12040 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
12042 header->locals [i] = image_g_new0 (image, MonoType, 1);
12043 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12044 mono_error_assert_ok (error);
12045 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12048 header->num_clauses = num_clauses;
12050 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12051 rmb->ilgen, num_clauses, error);
12052 mono_error_assert_ok (error);
12055 wrapperm->header = header;
12058 if (rmb->generic_params) {
12059 int count = mono_array_length (rmb->generic_params);
12060 MonoGenericContainer *container = rmb->generic_container;
12062 g_assert (container);
12064 container->type_argc = count;
12065 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12066 container->owner.method = m;
12067 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12069 m->is_generic = TRUE;
12070 mono_method_set_generic_container (m, container);
12072 for (i = 0; i < count; i++) {
12073 MonoReflectionGenericParam *gp =
12074 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12075 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12076 mono_error_assert_ok (error);
12077 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12078 container->type_params [i] = *param;
12082 * The method signature might have pointers to generic parameters that belong to other methods.
12083 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12084 * generic parameters.
12086 for (i = 0; i < m->signature->param_count; ++i) {
12087 MonoType *t = m->signature->params [i];
12088 if (t->type == MONO_TYPE_MVAR) {
12089 MonoGenericParam *gparam = t->data.generic_param;
12090 if (gparam->num < count) {
12091 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12092 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12098 if (klass->generic_container) {
12099 container->parent = klass->generic_container;
12100 container->context.class_inst = klass->generic_container->context.class_inst;
12102 container->context.method_inst = mono_get_shared_generic_inst (container);
12106 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12110 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12112 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12113 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12114 for (i = 0; i < rmb->nrefs; ++i)
12115 data [i + 1] = rmb->refs [i];
12120 /* Parameter info */
12123 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12124 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12125 for (i = 0; i <= m->signature->param_count; ++i) {
12126 MonoReflectionParamBuilder *pb;
12127 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12128 if ((i > 0) && (pb->attrs)) {
12129 /* Make a copy since it might point to a shared type structure */
12130 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12131 m->signature->params [i - 1]->attrs = pb->attrs;
12134 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12135 MonoDynamicImage *assembly;
12137 MonoTypeEnum def_type;
12141 if (!method_aux->param_defaults) {
12142 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12143 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12145 assembly = (MonoDynamicImage*)klass->image;
12146 idx = encode_constant (assembly, pb->def_value, &def_type);
12147 /* Copy the data from the blob since it might get realloc-ed */
12148 p = assembly->blob.data + idx;
12149 len = mono_metadata_decode_blob_size (p, &p2);
12151 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12152 method_aux->param_default_types [i] = def_type;
12153 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12157 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12158 mono_error_assert_ok (error);
12161 if (!method_aux->param_cattr)
12162 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12163 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12169 /* Parameter marshalling */
12172 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12173 MonoReflectionParamBuilder *pb;
12174 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12175 if (pb->marshal_info) {
12177 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12178 specs [pb->position] =
12179 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12180 if (!is_ok (error)) {
12181 mono_loader_unlock ();
12182 image_g_free (image, specs);
12183 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12189 if (specs != NULL) {
12191 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12192 method_aux->param_marshall = specs;
12195 if (image_is_dynamic (klass->image) && method_aux)
12196 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12198 mono_loader_unlock ();
12204 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12206 ReflectionMethodBuilder rmb;
12207 MonoMethodSignature *sig;
12209 mono_loader_lock ();
12210 g_assert (klass->image != NULL);
12211 sig = ctor_builder_to_signature (klass->image, mb, error);
12212 mono_loader_unlock ();
12213 return_val_if_nok (error, NULL);
12215 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12218 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12219 return_val_if_nok (error, NULL);
12220 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12222 /* If we are in a generic class, we might be called multiple times from inflate_method */
12223 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12224 /* ilgen is no longer needed */
12228 return mb->mhandle;
12232 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12234 ReflectionMethodBuilder rmb;
12235 MonoMethodSignature *sig;
12237 mono_error_init (error);
12239 mono_loader_lock ();
12240 g_assert (klass->image != NULL);
12241 sig = method_builder_to_signature (klass->image, mb, error);
12242 mono_loader_unlock ();
12243 return_val_if_nok (error, NULL);
12245 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12248 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12249 return_val_if_nok (error, NULL);
12250 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12252 /* If we are in a generic class, we might be called multiple times from inflate_method */
12253 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12254 /* ilgen is no longer needed */
12257 return mb->mhandle;
12260 static MonoClassField*
12261 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12263 MonoClassField *field;
12266 mono_error_init (error);
12268 field = g_new0 (MonoClassField, 1);
12270 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12271 mono_error_assert_ok (error);
12272 if (fb->attrs || fb->modreq || fb->modopt) {
12273 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12274 if (!is_ok (error)) {
12278 field->type = mono_metadata_type_dup (NULL, type);
12279 field->type->attrs = fb->attrs;
12281 g_assert (image_is_dynamic (klass->image));
12282 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12283 g_free (field->type);
12284 if (!is_ok (error)) {
12288 field->type = mono_metadata_type_dup (klass->image, custom);
12291 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12292 if (!is_ok (error)) {
12297 if (fb->offset != -1)
12298 field->offset = fb->offset;
12299 field->parent = klass;
12300 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12302 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12309 * mono_reflection_bind_generic_parameters:
12310 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12311 * @type_args: the number of type arguments to bind
12312 * @types: array of type arguments
12313 * @error: set on error
12315 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12316 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12319 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12322 MonoReflectionTypeBuilder *tb = NULL;
12323 gboolean is_dynamic = FALSE;
12324 MonoClass *geninst;
12326 mono_error_init (error);
12328 mono_loader_lock ();
12330 if (is_sre_type_builder (mono_object_class (type))) {
12331 tb = (MonoReflectionTypeBuilder *) type;
12334 } else if (is_sre_generic_instance (mono_object_class (type))) {
12335 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12336 MonoReflectionType *gtd = rgi->generic_type;
12338 if (is_sre_type_builder (mono_object_class (gtd))) {
12339 tb = (MonoReflectionTypeBuilder *)gtd;
12344 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12345 if (tb && tb->generic_container) {
12346 if (!mono_reflection_create_generic_class (tb, error)) {
12347 mono_loader_unlock ();
12352 MonoType *t = mono_reflection_type_get_handle (type, error);
12353 if (!is_ok (error)) {
12354 mono_loader_unlock ();
12358 klass = mono_class_from_mono_type (t);
12359 if (!klass->generic_container) {
12360 mono_loader_unlock ();
12361 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12365 if (klass->wastypebuilder) {
12366 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12371 mono_loader_unlock ();
12373 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12375 return &geninst->byval_arg;
12379 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12381 MonoGenericClass *gclass;
12382 MonoGenericInst *inst;
12384 g_assert (klass->generic_container);
12386 inst = mono_metadata_get_generic_inst (type_argc, types);
12387 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12389 return mono_generic_class_get_class (gclass);
12392 static MonoReflectionMethod*
12393 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12396 MonoMethod *method, *inflated;
12397 MonoMethodInflated *imethod;
12398 MonoGenericContext tmp_context;
12399 MonoGenericInst *ginst;
12400 MonoType **type_argv;
12403 mono_error_init (error);
12405 /*FIXME but this no longer should happen*/
12406 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12407 #ifndef DISABLE_REFLECTION_EMIT
12408 MonoReflectionMethodBuilder *mb = NULL;
12412 mb = (MonoReflectionMethodBuilder *) rmethod;
12413 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12414 return_val_if_nok (error, NULL);
12415 klass = mono_class_from_mono_type (tb);
12417 method = methodbuilder_to_mono_method (klass, mb, error);
12418 return_val_if_nok (error, NULL);
12420 g_assert_not_reached ();
12424 method = rmethod->method;
12427 klass = method->klass;
12429 if (method->is_inflated)
12430 method = ((MonoMethodInflated *) method)->declaring;
12432 count = mono_method_signature (method)->generic_param_count;
12433 if (count != mono_array_length (types))
12436 type_argv = g_new0 (MonoType *, count);
12437 for (i = 0; i < count; i++) {
12438 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12439 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12440 if (!is_ok (error)) {
12441 g_free (type_argv);
12445 ginst = mono_metadata_get_generic_inst (count, type_argv);
12446 g_free (type_argv);
12448 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12449 tmp_context.method_inst = ginst;
12451 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12452 mono_error_assert_ok (error);
12453 imethod = (MonoMethodInflated *) inflated;
12455 /*FIXME but I think this is no longer necessary*/
12456 if (image_is_dynamic (method->klass->image)) {
12457 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12459 * This table maps metadata structures representing inflated methods/fields
12460 * to the reflection objects representing their generic definitions.
12462 mono_image_lock ((MonoImage*)image);
12463 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12464 mono_image_unlock ((MonoImage*)image);
12467 if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12468 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12472 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12476 MonoReflectionMethod*
12477 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12480 MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12481 mono_error_set_pending_exception (&error);
12486 #ifndef DISABLE_REFLECTION_EMIT
12488 static MonoMethod *
12489 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12491 MonoMethodInflated *imethod;
12492 MonoGenericContext *context;
12496 * With generic code sharing the klass might not be inflated.
12497 * This can happen because classes inflated with their own
12498 * type arguments are "normalized" to the uninflated class.
12500 if (!klass->generic_class)
12503 context = mono_class_get_context (klass);
12505 if (klass->method.count && klass->methods) {
12506 /* Find the already created inflated method */
12507 for (i = 0; i < klass->method.count; ++i) {
12508 g_assert (klass->methods [i]->is_inflated);
12509 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12512 g_assert (i < klass->method.count);
12513 imethod = (MonoMethodInflated*)klass->methods [i];
12516 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12517 mono_error_assert_ok (&error);
12520 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12521 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12523 mono_image_lock ((MonoImage*)image);
12524 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12525 mono_image_unlock ((MonoImage*)image);
12527 return (MonoMethod *) imethod;
12530 static MonoMethod *
12531 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12533 MonoMethod *method;
12536 mono_error_init (error);
12538 MonoClass *type_class = mono_object_class (type);
12540 if (is_sre_generic_instance (type_class)) {
12541 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12542 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12543 return_val_if_nok (error, NULL);
12544 gklass = mono_class_from_mono_type (generic_type);
12545 } else if (is_sre_type_builder (type_class)) {
12546 MonoType *t = mono_reflection_type_get_handle (type, error);
12547 return_val_if_nok (error, NULL);
12548 gklass = mono_class_from_mono_type (t);
12549 } else if (type->type) {
12550 gklass = mono_class_from_mono_type (type->type);
12551 gklass = mono_class_get_generic_type_definition (gklass);
12553 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12556 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12557 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12558 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12560 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12564 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12565 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12568 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12569 method = ((MonoReflectionMethod *) obj)->method;
12571 method = NULL; /* prevent compiler warning */
12572 g_error ("can't handle type %s", obj->vtable->klass->name);
12575 MonoType *t = mono_reflection_type_get_handle (type, error);
12576 return_val_if_nok (error, NULL);
12577 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12580 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12582 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12584 MonoGenericClass *gclass;
12585 MonoDynamicGenericClass *dgclass;
12586 MonoClass *klass, *gklass;
12590 mono_error_init (error);
12592 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12593 return_val_if_nok (error, FALSE);
12594 klass = mono_class_from_mono_type (gtype);
12595 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12596 gclass = gtype->data.generic_class;
12598 if (!gclass->is_dynamic)
12601 dgclass = (MonoDynamicGenericClass *) gclass;
12603 if (dgclass->initialized)
12606 gklass = gclass->container_class;
12607 mono_class_init (gklass);
12609 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12611 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12612 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12613 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12615 for (i = 0; i < dgclass->count_fields; i++) {
12616 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12617 MonoClassField *field, *inflated_field = NULL;
12619 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12620 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12621 return_val_if_nok (error, FALSE);
12622 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12623 field = ((MonoReflectionField *) obj)->field;
12625 field = NULL; /* prevent compiler warning */
12626 g_assert_not_reached ();
12629 dgclass->fields [i] = *field;
12630 dgclass->fields [i].parent = klass;
12631 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12632 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12633 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12634 dgclass->field_generic_types [i] = field->type;
12635 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12636 dgclass->field_objects [i] = obj;
12638 if (inflated_field) {
12639 g_free (inflated_field);
12641 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12645 dgclass->initialized = TRUE;
12650 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12653 (void) reflection_generic_class_initialize (type, fields, &error);
12654 mono_error_set_pending_exception (&error);
12658 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12660 MonoDynamicGenericClass *dgclass;
12663 g_assert (gclass->is_dynamic);
12665 dgclass = (MonoDynamicGenericClass *)gclass;
12667 for (i = 0; i < dgclass->count_fields; ++i) {
12668 MonoClassField *field = dgclass->fields + i;
12669 mono_metadata_free_type (field->type);
12670 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12675 * fix_partial_generic_class:
12676 * @klass: a generic instantiation MonoClass
12677 * @error: set on error
12679 * Assumes that the generic container of @klass has its vtable
12680 * initialized, and updates the parent class, insterfaces, methods and
12681 * fields of @klass by inflating the types using the generic context.
12683 * On success returns TRUE, on failure returns FALSE and sets @error.
12687 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12689 MonoClass *gklass = klass->generic_class->container_class;
12690 MonoDynamicGenericClass *dgclass;
12693 mono_error_init (error);
12695 if (klass->wastypebuilder)
12698 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12699 if (klass->parent != gklass->parent) {
12700 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12701 if (mono_error_ok (error)) {
12702 MonoClass *parent = mono_class_from_mono_type (parent_type);
12703 mono_metadata_free_type (parent_type);
12704 if (parent != klass->parent) {
12705 /*fool mono_class_setup_parent*/
12706 klass->supertypes = NULL;
12707 mono_class_setup_parent (klass, parent);
12710 if (gklass->wastypebuilder)
12711 klass->wastypebuilder = TRUE;
12716 if (!dgclass->initialized)
12719 if (klass->method.count != gklass->method.count) {
12720 klass->method.count = gklass->method.count;
12721 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12723 for (i = 0; i < klass->method.count; i++) {
12724 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12725 gklass->methods [i], klass, mono_class_get_context (klass), error);
12726 mono_error_assert_ok (error);
12730 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12731 klass->interface_count = gklass->interface_count;
12732 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12733 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12735 for (i = 0; i < gklass->interface_count; ++i) {
12736 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12737 return_val_if_nok (error, FALSE);
12739 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12740 mono_metadata_free_type (iface_type);
12742 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12745 klass->interfaces_inited = 1;
12748 if (klass->field.count != gklass->field.count) {
12749 klass->field.count = gklass->field.count;
12750 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12752 for (i = 0; i < klass->field.count; i++) {
12753 klass->fields [i] = gklass->fields [i];
12754 klass->fields [i].parent = klass;
12755 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12756 return_val_if_nok (error, FALSE);
12760 /*We can only finish with this klass once it's parent has as well*/
12761 if (gklass->wastypebuilder)
12762 klass->wastypebuilder = TRUE;
12767 * ensure_generic_class_runtime_vtable:
12768 * @klass a generic class
12769 * @error set on error
12771 * Ensures that the generic container of @klass has a vtable and
12772 * returns TRUE on success. On error returns FALSE and sets @error.
12775 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12777 MonoClass *gklass = klass->generic_class->container_class;
12779 mono_error_init (error);
12781 if (!ensure_runtime_vtable (gklass, error))
12784 return fix_partial_generic_class (klass, error);
12788 * ensure_runtime_vtable:
12790 * @error set on error
12792 * Ensures that @klass has a vtable and returns TRUE on success. On
12793 * error returns FALSE and sets @error.
12796 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12798 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12801 mono_error_init (error);
12803 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12806 if (!ensure_runtime_vtable (klass->parent, error))
12810 num = tb->ctors? mono_array_length (tb->ctors): 0;
12811 num += tb->num_methods;
12812 klass->method.count = num;
12813 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12814 num = tb->ctors? mono_array_length (tb->ctors): 0;
12815 for (i = 0; i < num; ++i) {
12816 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12819 klass->methods [i] = ctor;
12821 num = tb->num_methods;
12823 for (i = 0; i < num; ++i) {
12824 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12827 klass->methods [j++] = meth;
12830 if (tb->interfaces) {
12831 klass->interface_count = mono_array_length (tb->interfaces);
12832 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12833 for (i = 0; i < klass->interface_count; ++i) {
12834 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12835 return_val_if_nok (error, FALSE);
12836 klass->interfaces [i] = mono_class_from_mono_type (iface);
12837 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12840 klass->interfaces_inited = 1;
12842 } else if (klass->generic_class){
12843 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12844 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12849 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12851 for (i = 0; i < klass->method.count; ++i) {
12852 MonoMethod *im = klass->methods [i];
12853 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12854 im->slot = slot_num++;
12857 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12858 mono_class_setup_interface_offsets (klass);
12859 mono_class_setup_interface_id (klass);
12863 * The generic vtable is needed even if image->run is not set since some
12864 * runtime code like ves_icall_Type_GetMethodsByName depends on
12865 * method->slot being defined.
12869 * tb->methods could not be freed since it is used for determining
12870 * overrides during dynamic vtable construction.
12877 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12879 mono_error_init (error);
12880 MonoClass *klass = mono_object_class (method);
12881 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12882 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12883 return sr_method->method;
12885 if (is_sre_method_builder (klass)) {
12886 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12887 return mb->mhandle;
12889 if (is_sre_method_on_tb_inst (klass)) {
12890 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12891 MonoMethod *result;
12892 /*FIXME move this to a proper method and unify with resolve_object*/
12893 if (m->method_args) {
12894 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12896 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12897 return_val_if_nok (error, NULL);
12898 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12899 MonoMethod *mono_method;
12901 if (is_sre_method_builder (mono_object_class (m->mb)))
12902 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12903 else if (is_sr_mono_method (mono_object_class (m->mb)))
12904 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12906 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)));
12908 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12913 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12918 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12920 MonoReflectionTypeBuilder *tb;
12922 MonoReflectionMethod *m;
12924 mono_error_init (error);
12926 *num_overrides = 0;
12928 g_assert (image_is_dynamic (klass->image));
12930 if (!mono_class_get_ref_info (klass))
12933 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12935 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12939 for (i = 0; i < tb->num_methods; ++i) {
12940 MonoReflectionMethodBuilder *mb =
12941 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12942 if (mb->override_methods)
12943 onum += mono_array_length (mb->override_methods);
12948 *overrides = g_new0 (MonoMethod*, onum * 2);
12951 for (i = 0; i < tb->num_methods; ++i) {
12952 MonoReflectionMethodBuilder *mb =
12953 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12954 if (mb->override_methods) {
12955 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12956 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12958 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12959 return_if_nok (error);
12960 (*overrides) [onum * 2 + 1] = mb->mhandle;
12962 g_assert (mb->mhandle);
12970 *num_overrides = onum;
12974 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12976 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12977 MonoReflectionFieldBuilder *fb;
12978 MonoClassField *field;
12979 MonoImage *image = klass->image;
12980 const char *p, *p2;
12982 guint32 len, idx, real_size = 0;
12984 klass->field.count = tb->num_fields;
12985 klass->field.first = 0;
12987 mono_error_init (error);
12989 if (tb->class_size) {
12990 if ((tb->packing_size & 0xffffff00) != 0) {
12991 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12992 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12995 klass->packing_size = tb->packing_size;
12996 real_size = klass->instance_size + tb->class_size;
12999 if (!klass->field.count) {
13000 klass->instance_size = MAX (klass->instance_size, real_size);
13004 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
13005 mono_class_alloc_ext (klass);
13006 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
13008 This is, guess what, a hack.
13009 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
13010 On the static path no field class is resolved, only types are built. This is the right thing to do
13012 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
13014 klass->size_inited = 1;
13016 for (i = 0; i < klass->field.count; ++i) {
13017 MonoArray *rva_data;
13018 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13019 field = &klass->fields [i];
13020 field->name = mono_string_to_utf8_image (image, fb->name, error);
13021 if (!mono_error_ok (error))
13024 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13025 return_if_nok (error);
13026 field->type = mono_metadata_type_dup (klass->image, type);
13027 field->type->attrs = fb->attrs;
13029 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13030 return_if_nok (error);
13033 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
13034 char *base = mono_array_addr (rva_data, char, 0);
13035 size_t size = mono_array_length (rva_data);
13036 char *data = (char *)mono_image_alloc (klass->image, size);
13037 memcpy (data, base, size);
13038 klass->ext->field_def_values [i].data = data;
13040 if (fb->offset != -1)
13041 field->offset = fb->offset;
13042 field->parent = klass;
13043 fb->handle = field;
13044 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13046 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13047 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13049 if (fb->def_value) {
13050 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13051 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13052 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13053 /* Copy the data from the blob since it might get realloc-ed */
13054 p = assembly->blob.data + idx;
13055 len = mono_metadata_decode_blob_size (p, &p2);
13057 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13058 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13062 klass->instance_size = MAX (klass->instance_size, real_size);
13063 mono_class_layout_fields (klass, klass->instance_size);
13067 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13069 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13070 MonoReflectionPropertyBuilder *pb;
13071 MonoImage *image = klass->image;
13072 MonoProperty *properties;
13075 mono_error_init (error);
13078 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13080 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13081 klass->ext->property.first = 0;
13083 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13084 klass->ext->properties = properties;
13085 for (i = 0; i < klass->ext->property.count; ++i) {
13086 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13087 properties [i].parent = klass;
13088 properties [i].attrs = pb->attrs;
13089 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13090 if (!mono_error_ok (error))
13092 if (pb->get_method)
13093 properties [i].get = pb->get_method->mhandle;
13094 if (pb->set_method)
13095 properties [i].set = pb->set_method->mhandle;
13097 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13098 if (pb->def_value) {
13100 const char *p, *p2;
13101 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13102 if (!klass->ext->prop_def_values)
13103 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13104 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13105 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13106 /* Copy the data from the blob since it might get realloc-ed */
13107 p = assembly->blob.data + idx;
13108 len = mono_metadata_decode_blob_size (p, &p2);
13110 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13111 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13116 static MonoReflectionEvent *
13117 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13119 mono_error_init (error);
13121 MonoEvent *event = g_new0 (MonoEvent, 1);
13124 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13125 if (!is_ok (error)) {
13129 klass = mono_class_from_mono_type (type);
13131 event->parent = klass;
13132 event->attrs = eb->attrs;
13133 event->name = mono_string_to_utf8_checked (eb->name, error);
13134 if (!is_ok (error)) {
13138 if (eb->add_method)
13139 event->add = eb->add_method->mhandle;
13140 if (eb->remove_method)
13141 event->remove = eb->remove_method->mhandle;
13142 if (eb->raise_method)
13143 event->raise = eb->raise_method->mhandle;
13145 #ifndef MONO_SMALL_CONFIG
13146 if (eb->other_methods) {
13148 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13149 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13150 MonoReflectionMethodBuilder *mb =
13151 mono_array_get (eb->other_methods,
13152 MonoReflectionMethodBuilder*, j);
13153 event->other [j] = mb->mhandle;
13158 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13159 if (!is_ok (error)) {
13160 #ifndef MONO_SMALL_CONFIG
13161 g_free (event->other);
13169 MonoReflectionEvent *
13170 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13173 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13174 mono_error_set_pending_exception (&error);
13179 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13182 MonoReflectionEventBuilder *eb;
13183 MonoImage *image = klass->image;
13187 mono_error_init (error);
13190 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13192 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13193 klass->ext->event.first = 0;
13195 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13196 klass->ext->events = events;
13197 for (i = 0; i < klass->ext->event.count; ++i) {
13198 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13199 events [i].parent = klass;
13200 events [i].attrs = eb->attrs;
13201 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13202 if (!mono_error_ok (error))
13204 if (eb->add_method)
13205 events [i].add = eb->add_method->mhandle;
13206 if (eb->remove_method)
13207 events [i].remove = eb->remove_method->mhandle;
13208 if (eb->raise_method)
13209 events [i].raise = eb->raise_method->mhandle;
13211 #ifndef MONO_SMALL_CONFIG
13212 if (eb->other_methods) {
13214 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13215 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13216 MonoReflectionMethodBuilder *mb =
13217 mono_array_get (eb->other_methods,
13218 MonoReflectionMethodBuilder*, j);
13219 events [i].other [j] = mb->mhandle;
13223 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13227 struct remove_instantiations_user_data
13234 remove_instantiations_of_and_ensure_contents (gpointer key,
13236 gpointer user_data)
13238 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13239 MonoType *type = (MonoType*)key;
13240 MonoClass *klass = data->klass;
13241 gboolean already_failed = !is_ok (data->error);
13243 MonoError *error = already_failed ? &lerror : data->error;
13245 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13246 MonoClass *inst_klass = mono_class_from_mono_type (type);
13247 //Ensure it's safe to use it.
13248 if (!fix_partial_generic_class (inst_klass, error)) {
13249 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13250 // Marked the class with failure, but since some other instantiation already failed,
13251 // just report that one, and swallow the error from this one.
13252 if (already_failed)
13253 mono_error_cleanup (error);
13261 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13263 mono_error_init (error);
13269 for (i = 0; i < mono_array_length (arr); ++i) {
13270 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13271 if (!mono_error_ok (error))
13276 MonoReflectionType*
13277 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13281 MonoDomain* domain;
13282 MonoReflectionType* res;
13285 mono_error_init (&error);
13287 domain = mono_object_domain (tb);
13288 klass = mono_class_from_mono_type (tb->type.type);
13291 * Check for user defined Type subclasses.
13293 RESOLVE_TYPE (tb->parent, &error);
13294 if (!is_ok (&error))
13295 goto failure_unlocked;
13296 check_array_for_usertypes (tb->interfaces, &error);
13297 if (!is_ok (&error))
13298 goto failure_unlocked;
13300 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13301 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13303 RESOLVE_TYPE (fb->type, &error);
13304 if (!is_ok (&error))
13305 goto failure_unlocked;
13306 check_array_for_usertypes (fb->modreq, &error);
13307 if (!is_ok (&error))
13308 goto failure_unlocked;
13309 check_array_for_usertypes (fb->modopt, &error);
13310 if (!is_ok (&error))
13311 goto failure_unlocked;
13312 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13313 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13314 if (!is_ok (&error))
13315 goto failure_unlocked;
13321 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13322 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13324 RESOLVE_TYPE (mb->rtype, &error);
13325 if (!is_ok (&error))
13326 goto failure_unlocked;
13327 check_array_for_usertypes (mb->return_modreq, &error);
13328 if (!is_ok (&error))
13329 goto failure_unlocked;
13330 check_array_for_usertypes (mb->return_modopt, &error);
13331 if (!is_ok (&error))
13332 goto failure_unlocked;
13333 check_array_for_usertypes (mb->parameters, &error);
13334 if (!is_ok (&error))
13335 goto failure_unlocked;
13336 if (mb->param_modreq)
13337 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13338 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13339 if (!is_ok (&error))
13340 goto failure_unlocked;
13342 if (mb->param_modopt)
13343 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13344 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13345 if (!is_ok (&error))
13346 goto failure_unlocked;
13352 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13353 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13355 check_array_for_usertypes (mb->parameters, &error);
13356 if (!is_ok (&error))
13357 goto failure_unlocked;
13358 if (mb->param_modreq)
13359 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13360 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13361 if (!is_ok (&error))
13362 goto failure_unlocked;
13364 if (mb->param_modopt)
13365 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13366 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13367 if (!is_ok (&error))
13368 goto failure_unlocked;
13374 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13377 * we need to lock the domain because the lock will be taken inside
13378 * So, we need to keep the locking order correct.
13380 mono_loader_lock ();
13381 mono_domain_lock (domain);
13382 if (klass->wastypebuilder) {
13383 mono_domain_unlock (domain);
13384 mono_loader_unlock ();
13386 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13387 mono_error_set_pending_exception (&error);
13392 * Fields to set in klass:
13393 * the various flags: delegate/unicode/contextbound etc.
13395 klass->flags = tb->attrs;
13396 klass->has_cctor = 1;
13398 mono_class_setup_parent (klass, klass->parent);
13399 /* fool mono_class_setup_supertypes */
13400 klass->supertypes = NULL;
13401 mono_class_setup_supertypes (klass);
13402 mono_class_setup_mono_type (klass);
13405 if (!((MonoDynamicImage*)klass->image)->run) {
13406 if (klass->generic_container) {
13407 /* FIXME: The code below can't handle generic classes */
13408 klass->wastypebuilder = TRUE;
13409 mono_loader_unlock ();
13410 mono_domain_unlock (domain);
13412 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13413 mono_error_set_pending_exception (&error);
13420 /* enums are done right away */
13421 if (!klass->enumtype)
13422 if (!ensure_runtime_vtable (klass, &error))
13425 if (tb->subtypes) {
13426 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13427 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13428 mono_class_alloc_ext (klass);
13429 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13430 if (!is_ok (&error)) goto failure;
13431 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13435 klass->nested_classes_inited = TRUE;
13437 /* fields and object layout */
13438 if (klass->parent) {
13439 if (!klass->parent->size_inited)
13440 mono_class_init (klass->parent);
13441 klass->instance_size = klass->parent->instance_size;
13442 klass->sizes.class_size = 0;
13443 klass->min_align = klass->parent->min_align;
13444 /* if the type has no fields we won't call the field_setup
13445 * routine which sets up klass->has_references.
13447 klass->has_references |= klass->parent->has_references;
13449 klass->instance_size = sizeof (MonoObject);
13450 klass->min_align = 1;
13453 /* FIXME: handle packing_size and instance_size */
13454 typebuilder_setup_fields (klass, &error);
13455 if (!mono_error_ok (&error))
13457 typebuilder_setup_properties (klass, &error);
13458 if (!mono_error_ok (&error))
13461 typebuilder_setup_events (klass, &error);
13462 if (!mono_error_ok (&error))
13465 klass->wastypebuilder = TRUE;
13468 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13469 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13470 * we want to return normal System.MonoType objects, so clear these out from the cache.
13472 * Together with this we must ensure the contents of all instances to match the created type.
13474 if (domain->type_hash && klass->generic_container) {
13475 struct remove_instantiations_user_data data;
13476 data.klass = klass;
13477 data.error = &error;
13478 mono_error_assert_ok (&error);
13479 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13480 if (!is_ok (&error))
13484 mono_domain_unlock (domain);
13485 mono_loader_unlock ();
13487 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13488 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13489 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13490 goto failure_unlocked;
13493 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13494 if (!is_ok (&error))
13495 goto failure_unlocked;
13497 g_assert (res != (MonoReflectionType*)tb);
13502 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13503 klass->wastypebuilder = TRUE;
13504 mono_domain_unlock (domain);
13505 mono_loader_unlock ();
13507 mono_error_set_pending_exception (&error);
13512 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13514 MonoGenericParamFull *param;
13518 mono_error_init (error);
13520 image = &gparam->tbuilder->module->dynamic_image->image;
13522 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13524 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13525 mono_error_assert_ok (error);
13526 param->param.num = gparam->index;
13528 if (gparam->mbuilder) {
13529 if (!gparam->mbuilder->generic_container) {
13530 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13531 return_val_if_nok (error, FALSE);
13533 MonoClass *klass = mono_class_from_mono_type (tb);
13534 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13535 gparam->mbuilder->generic_container->is_method = TRUE;
13537 * Cannot set owner.method, since the MonoMethod is not created yet.
13538 * Set the image field instead, so type_in_image () works.
13540 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13541 gparam->mbuilder->generic_container->owner.image = klass->image;
13543 param->param.owner = gparam->mbuilder->generic_container;
13544 } else if (gparam->tbuilder) {
13545 if (!gparam->tbuilder->generic_container) {
13546 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13547 return_val_if_nok (error, FALSE);
13548 MonoClass *klass = mono_class_from_mono_type (tb);
13549 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13550 gparam->tbuilder->generic_container->owner.klass = klass;
13552 param->param.owner = gparam->tbuilder->generic_container;
13555 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13557 gparam->type.type = &pklass->byval_arg;
13559 mono_class_set_ref_info (pklass, gparam);
13560 mono_image_append_class_to_reflection_info_set (pklass);
13566 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13569 (void) reflection_initialize_generic_parameter (gparam, &error);
13570 mono_error_set_pending_exception (&error);
13575 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13577 MonoReflectionModuleBuilder *module = sig->module;
13578 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13579 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13584 mono_error_init (error);
13586 check_array_for_usertypes (sig->arguments, error);
13587 return_val_if_nok (error, NULL);
13589 sigbuffer_init (&buf, 32);
13591 sigbuffer_add_value (&buf, 0x07);
13592 sigbuffer_add_value (&buf, na);
13593 if (assembly != NULL){
13594 for (i = 0; i < na; ++i) {
13595 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13596 encode_reflection_type (assembly, type, &buf, error);
13597 if (!is_ok (error)) goto fail;
13601 buflen = buf.p - buf.buf;
13602 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13603 if (!is_ok (error)) goto fail;
13604 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13605 sigbuffer_free (&buf);
13608 sigbuffer_free (&buf);
13613 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13616 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13617 mono_error_set_pending_exception (&error);
13622 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13624 MonoDynamicImage *assembly = sig->module->dynamic_image;
13625 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13630 mono_error_init (error);
13632 check_array_for_usertypes (sig->arguments, error);
13633 return_val_if_nok (error, NULL);
13635 sigbuffer_init (&buf, 32);
13637 sigbuffer_add_value (&buf, 0x06);
13638 for (i = 0; i < na; ++i) {
13639 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13640 encode_reflection_type (assembly, type, &buf, error);
13641 if (!is_ok (error))
13645 buflen = buf.p - buf.buf;
13646 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13647 if (!is_ok (error)) goto fail;
13648 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13649 sigbuffer_free (&buf);
13653 sigbuffer_free (&buf);
13658 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13661 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13662 mono_error_set_pending_exception (&error);
13667 MonoMethod *handle;
13668 MonoDomain *domain;
13669 } DynamicMethodReleaseData;
13672 * The runtime automatically clean up those after finalization.
13674 static MonoReferenceQueue *dynamic_method_queue;
13677 free_dynamic_method (void *dynamic_method)
13679 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13680 MonoDomain *domain = data->domain;
13681 MonoMethod *method = data->handle;
13684 mono_domain_lock (domain);
13685 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13686 g_hash_table_remove (domain->method_to_dyn_method, method);
13687 mono_domain_unlock (domain);
13688 g_assert (dis_link);
13689 mono_gchandle_free (dis_link);
13691 mono_runtime_free_method (domain, method);
13696 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13698 MonoReferenceQueue *queue;
13699 MonoMethod *handle;
13700 DynamicMethodReleaseData *release_data;
13701 ReflectionMethodBuilder rmb;
13702 MonoMethodSignature *sig;
13704 MonoDomain *domain;
13708 mono_error_init (error);
13710 if (mono_runtime_is_shutting_down ()) {
13711 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13715 if (!(queue = dynamic_method_queue)) {
13716 mono_loader_lock ();
13717 if (!(queue = dynamic_method_queue))
13718 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13719 mono_loader_unlock ();
13722 sig = dynamic_method_to_signature (mb, error);
13723 return_val_if_nok (error, FALSE);
13725 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13728 * Resolve references.
13731 * Every second entry in the refs array is reserved for storing handle_class,
13732 * which is needed by the ldtoken implementation in the JIT.
13734 rmb.nrefs = mb->nrefs;
13735 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13736 for (i = 0; i < mb->nrefs; i += 2) {
13737 MonoClass *handle_class;
13739 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13741 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13742 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13744 * The referenced DynamicMethod should already be created by the managed
13745 * code, except in the case of circular references. In that case, we store
13746 * method in the refs array, and fix it up later when the referenced
13747 * DynamicMethod is created.
13749 if (method->mhandle) {
13750 ref = method->mhandle;
13752 /* FIXME: GC object stored in unmanaged memory */
13755 /* FIXME: GC object stored in unmanaged memory */
13756 method->referenced_by = g_slist_append (method->referenced_by, mb);
13758 handle_class = mono_defaults.methodhandle_class;
13760 MonoException *ex = NULL;
13761 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13762 if (!is_ok (error)) {
13767 ex = mono_get_exception_type_load (NULL, NULL);
13768 else if (mono_security_core_clr_enabled ())
13769 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13773 mono_error_set_exception_instance (error, ex);
13778 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13779 rmb.refs [i + 1] = handle_class;
13783 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13784 if (!is_ok (error)) {
13788 klass = mono_class_from_mono_type (owner_type);
13790 klass = mono_defaults.object_class;
13793 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13795 return_val_if_nok (error, FALSE);
13797 release_data = g_new (DynamicMethodReleaseData, 1);
13798 release_data->handle = handle;
13799 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13800 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13801 g_free (release_data);
13803 /* Fix up refs entries pointing at us */
13804 for (l = mb->referenced_by; l; l = l->next) {
13805 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13806 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13809 g_assert (method->mhandle);
13811 data = (gpointer*)wrapper->method_data;
13812 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13813 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13814 data [i + 1] = mb->mhandle;
13817 g_slist_free (mb->referenced_by);
13819 /* ilgen is no longer needed */
13822 domain = mono_domain_get ();
13823 mono_domain_lock (domain);
13824 if (!domain->method_to_dyn_method)
13825 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13826 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13827 mono_domain_unlock (domain);
13833 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13836 (void) reflection_create_dynamic_method (mb, &error);
13837 mono_error_set_pending_exception (&error);
13840 #endif /* DISABLE_REFLECTION_EMIT */
13844 * mono_reflection_is_valid_dynamic_token:
13846 * Returns TRUE if token is valid.
13850 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13852 return lookup_dyn_token (image, token) != NULL;
13855 MonoMethodSignature *
13856 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13858 MonoMethodSignature *sig;
13859 g_assert (image_is_dynamic (image));
13861 mono_error_init (error);
13863 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13867 return mono_method_signature_checked (method, error);
13870 #ifndef DISABLE_REFLECTION_EMIT
13873 * mono_reflection_lookup_dynamic_token:
13875 * Finish the Builder object pointed to by TOKEN and return the corresponding
13876 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13877 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13880 * LOCKING: Take the loader lock
13883 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13885 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13889 mono_error_init (error);
13891 obj = lookup_dyn_token (assembly, token);
13894 g_error ("Could not find required dynamic token 0x%08x", token);
13896 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13902 handle_class = &klass;
13903 gpointer result = resolve_object (image, obj, handle_class, context, error);
13908 * ensure_complete_type:
13910 * Ensure that KLASS is completed if it is a dynamic type, or references
13914 ensure_complete_type (MonoClass *klass, MonoError *error)
13916 mono_error_init (error);
13918 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13919 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13921 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13922 return_if_nok (error);
13924 // Asserting here could break a lot of code
13925 //g_assert (klass->wastypebuilder);
13928 if (klass->generic_class) {
13929 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13932 for (i = 0; i < inst->type_argc; ++i) {
13933 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13934 return_if_nok (error);
13940 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13942 gpointer result = NULL;
13944 mono_error_init (error);
13946 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13947 result = mono_string_intern_checked ((MonoString*)obj, error);
13948 return_val_if_nok (error, NULL);
13949 *handle_class = mono_defaults.string_class;
13951 } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13952 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13953 return_val_if_nok (error, NULL);
13954 MonoClass *mc = mono_class_from_mono_type (type);
13955 if (!mono_class_init (mc)) {
13956 mono_error_set_for_class_failure (error, mc);
13961 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13962 return_val_if_nok (error, NULL);
13964 result = mono_class_from_mono_type (inflated);
13965 mono_metadata_free_type (inflated);
13967 result = mono_class_from_mono_type (type);
13969 *handle_class = mono_defaults.typehandle_class;
13971 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13972 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13973 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13974 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13975 result = ((MonoReflectionMethod*)obj)->method;
13977 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13978 mono_error_assert_ok (error);
13980 *handle_class = mono_defaults.methodhandle_class;
13982 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13983 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13984 result = mb->mhandle;
13986 /* Type is not yet created */
13987 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13989 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13990 return_val_if_nok (error, NULL);
13993 * Hopefully this has been filled in by calling CreateType() on the
13997 * TODO: This won't work if the application finishes another
13998 * TypeBuilder instance instead of this one.
14000 result = mb->mhandle;
14003 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14004 mono_error_assert_ok (error);
14006 *handle_class = mono_defaults.methodhandle_class;
14007 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
14008 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
14010 result = cb->mhandle;
14012 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
14014 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14015 return_val_if_nok (error, NULL);
14016 result = cb->mhandle;
14019 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14020 mono_error_assert_ok (error);
14022 *handle_class = mono_defaults.methodhandle_class;
14023 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
14024 MonoClassField *field = ((MonoReflectionField*)obj)->field;
14026 ensure_complete_type (field->parent, error);
14027 return_val_if_nok (error, NULL);
14030 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
14031 return_val_if_nok (error, NULL);
14033 MonoClass *klass = mono_class_from_mono_type (inflated);
14034 MonoClassField *inflated_field;
14035 gpointer iter = NULL;
14036 mono_metadata_free_type (inflated);
14037 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
14038 if (!strcmp (field->name, inflated_field->name))
14041 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
14042 result = inflated_field;
14046 *handle_class = mono_defaults.fieldhandle_class;
14048 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14049 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14050 result = fb->handle;
14053 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14055 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14056 return_val_if_nok (error, NULL);
14057 result = fb->handle;
14060 if (fb->handle && fb->handle->parent->generic_container) {
14061 MonoClass *klass = fb->handle->parent;
14062 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14063 return_val_if_nok (error, NULL);
14065 MonoClass *inflated = mono_class_from_mono_type (type);
14067 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14069 mono_metadata_free_type (type);
14071 *handle_class = mono_defaults.fieldhandle_class;
14072 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14073 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14074 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14075 return_val_if_nok (error, NULL);
14078 klass = type->data.klass;
14079 if (klass->wastypebuilder) {
14080 /* Already created */
14084 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14085 return_val_if_nok (error, NULL);
14086 result = type->data.klass;
14089 *handle_class = mono_defaults.typehandle_class;
14090 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14091 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14092 MonoMethodSignature *sig;
14095 if (helper->arguments)
14096 nargs = mono_array_length (helper->arguments);
14100 sig = mono_metadata_signature_alloc (image, nargs);
14101 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14102 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14104 if (helper->unmanaged_call_conv) { /* unmanaged */
14105 sig->call_convention = helper->unmanaged_call_conv - 1;
14106 sig->pinvoke = TRUE;
14107 } else if (helper->call_conv & 0x02) {
14108 sig->call_convention = MONO_CALL_VARARG;
14110 sig->call_convention = MONO_CALL_DEFAULT;
14113 sig->param_count = nargs;
14114 /* TODO: Copy type ? */
14115 sig->ret = helper->return_type->type;
14116 for (i = 0; i < nargs; ++i) {
14117 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14118 if (!is_ok (error)) {
14119 image_g_free (image, sig);
14125 *handle_class = NULL;
14126 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14127 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14128 /* Already created by the managed code */
14129 g_assert (method->mhandle);
14130 result = method->mhandle;
14131 *handle_class = mono_defaults.methodhandle_class;
14132 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14133 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14134 return_val_if_nok (error, NULL);
14135 type = mono_class_inflate_generic_type_checked (type, context, error);
14136 return_val_if_nok (error, NULL);
14138 result = mono_class_from_mono_type (type);
14139 *handle_class = mono_defaults.typehandle_class;
14141 mono_metadata_free_type (type);
14142 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14143 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14144 return_val_if_nok (error, NULL);
14145 type = mono_class_inflate_generic_type_checked (type, context, error);
14146 return_val_if_nok (error, NULL);
14148 result = mono_class_from_mono_type (type);
14149 *handle_class = mono_defaults.typehandle_class;
14151 mono_metadata_free_type (type);
14152 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14153 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14154 MonoClass *inflated;
14156 MonoClassField *field;
14158 if (is_sre_field_builder (mono_object_class (f->fb)))
14159 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14160 else if (is_sr_mono_field (mono_object_class (f->fb)))
14161 field = ((MonoReflectionField*)f->fb)->field;
14163 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)));
14165 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14166 return_val_if_nok (error, NULL);
14167 type = mono_class_inflate_generic_type_checked (finst, context, error);
14168 return_val_if_nok (error, NULL);
14170 inflated = mono_class_from_mono_type (type);
14172 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14173 ensure_complete_type (field->parent, error);
14174 if (!is_ok (error)) {
14175 mono_metadata_free_type (type);
14180 mono_metadata_free_type (type);
14181 *handle_class = mono_defaults.fieldhandle_class;
14182 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14183 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14184 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14185 return_val_if_nok (error, NULL);
14186 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14187 return_val_if_nok (error, NULL);
14189 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14190 MonoMethod *method;
14192 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14193 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14194 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14195 method = ((MonoReflectionMethod *)c->cb)->method;
14197 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)));
14199 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14200 *handle_class = mono_defaults.methodhandle_class;
14201 mono_metadata_free_type (type);
14202 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14203 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14204 if (m->method_args) {
14205 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14206 return_val_if_nok (error, NULL);
14208 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14209 mono_error_assert_ok (error);
14212 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14213 return_val_if_nok (error, NULL);
14214 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14215 return_val_if_nok (error, NULL);
14217 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14218 MonoMethod *method;
14220 if (is_sre_method_builder (mono_object_class (m->mb)))
14221 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14222 else if (is_sr_mono_method (mono_object_class (m->mb)))
14223 method = ((MonoReflectionMethod *)m->mb)->method;
14225 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)));
14227 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14228 mono_metadata_free_type (type);
14230 *handle_class = mono_defaults.methodhandle_class;
14231 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14232 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14235 MonoMethod *method;
14239 mtype = mono_reflection_type_get_handle (m->parent, error);
14240 return_val_if_nok (error, NULL);
14241 klass = mono_class_from_mono_type (mtype);
14243 /* Find the method */
14245 name = mono_string_to_utf8_checked (m->name, error);
14246 return_val_if_nok (error, NULL);
14248 while ((method = mono_class_get_methods (klass, &iter))) {
14249 if (!strcmp (method->name, name))
14256 // FIXME: Check parameters/return value etc. match
14259 *handle_class = mono_defaults.methodhandle_class;
14260 } else if (is_sre_array (mono_object_get_class(obj)) ||
14261 is_sre_byref (mono_object_get_class(obj)) ||
14262 is_sre_pointer (mono_object_get_class(obj))) {
14263 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14264 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14265 return_val_if_nok (error, NULL);
14268 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14269 return_val_if_nok (error, NULL);
14271 result = mono_class_from_mono_type (inflated);
14272 mono_metadata_free_type (inflated);
14274 result = mono_class_from_mono_type (type);
14276 *handle_class = mono_defaults.typehandle_class;
14278 g_print ("%s\n", obj->vtable->klass->name);
14279 g_assert_not_reached ();
14284 #else /* DISABLE_REFLECTION_EMIT */
14287 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14289 g_assert_not_reached ();
14294 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14296 g_assert_not_reached ();
14300 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14302 g_assert_not_reached ();
14306 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14308 g_assert_not_reached ();
14313 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14315 g_assert_not_reached ();
14319 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14321 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14325 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14327 g_assert_not_reached ();
14331 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14333 g_assert_not_reached ();
14336 MonoReflectionModule *
14337 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14339 g_assert_not_reached ();
14344 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14346 g_assert_not_reached ();
14351 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14353 g_assert_not_reached ();
14358 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14359 gboolean create_open_instance, gboolean register_token, MonoError *error)
14361 g_assert_not_reached ();
14366 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14371 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14373 g_assert_not_reached ();
14377 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14379 mono_error_init (error);
14381 *num_overrides = 0;
14384 MonoReflectionEvent *
14385 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14387 g_assert_not_reached ();
14391 MonoReflectionType*
14392 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14394 g_assert_not_reached ();
14399 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14401 g_assert_not_reached ();
14405 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14407 g_assert_not_reached ();
14412 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14414 g_assert_not_reached ();
14419 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14424 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14426 mono_error_init (error);
14431 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14433 mono_error_init (error);
14440 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14442 g_assert_not_reached ();
14445 #endif /* DISABLE_REFLECTION_EMIT */
14447 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14448 const static guint32 declsec_flags_map[] = {
14449 0x00000000, /* empty */
14450 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14451 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14452 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14453 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14454 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14455 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14456 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14457 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14458 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14459 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14460 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14461 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14462 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14463 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14464 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14465 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14466 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14467 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14471 * Returns flags that includes all available security action associated to the handle.
14472 * @token: metadata token (either for a class or a method)
14473 * @image: image where resides the metadata.
14476 mono_declsec_get_flags (MonoImage *image, guint32 token)
14478 int index = mono_metadata_declsec_from_index (image, token);
14479 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14480 guint32 result = 0;
14484 /* HasSecurity can be present for other, not specially encoded, attributes,
14485 e.g. SuppressUnmanagedCodeSecurityAttribute */
14489 for (i = index; i < t->rows; i++) {
14490 guint32 cols [MONO_DECL_SECURITY_SIZE];
14492 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14493 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14496 action = cols [MONO_DECL_SECURITY_ACTION];
14497 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14498 result |= declsec_flags_map [action];
14500 g_assert_not_reached ();
14507 * Get the security actions (in the form of flags) associated with the specified method.
14509 * @method: The method for which we want the declarative security flags.
14510 * Return the declarative security flags for the method (only).
14512 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14513 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14516 mono_declsec_flags_from_method (MonoMethod *method)
14518 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14519 /* FIXME: No cache (for the moment) */
14520 guint32 idx = mono_method_get_index (method);
14521 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14522 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14523 return mono_declsec_get_flags (method->klass->image, idx);
14529 * Get the security actions (in the form of flags) associated with the specified class.
14531 * @klass: The class for which we want the declarative security flags.
14532 * Return the declarative security flags for the class.
14534 * Note: We cache the flags inside the MonoClass structure as this will get
14535 * called very often (at least for each method).
14538 mono_declsec_flags_from_class (MonoClass *klass)
14540 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14541 if (!klass->ext || !klass->ext->declsec_flags) {
14544 idx = mono_metadata_token_index (klass->type_token);
14545 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14546 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14547 mono_loader_lock ();
14548 mono_class_alloc_ext (klass);
14549 mono_loader_unlock ();
14550 /* we cache the flags on classes */
14551 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14553 return klass->ext->declsec_flags;
14559 * Get the security actions (in the form of flags) associated with the specified assembly.
14561 * @assembly: The assembly for which we want the declarative security flags.
14562 * Return the declarative security flags for the assembly.
14565 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14567 guint32 idx = 1; /* there is only one assembly */
14568 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14569 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14570 return mono_declsec_get_flags (assembly->image, idx);
14575 * Fill actions for the specific index (which may either be an encoded class token or
14576 * an encoded method token) from the metadata image.
14577 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14580 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14581 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14583 MonoBoolean result = FALSE;
14585 guint32 cols [MONO_DECL_SECURITY_SIZE];
14586 int index = mono_metadata_declsec_from_index (image, token);
14589 t = &image->tables [MONO_TABLE_DECLSECURITY];
14590 for (i = index; i < t->rows; i++) {
14591 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14593 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14596 /* if present only replace (class) permissions with method permissions */
14597 /* if empty accept either class or method permissions */
14598 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14599 if (!actions->demand.blob) {
14600 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14601 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14602 actions->demand.blob = (char*) (blob + 2);
14603 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14606 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14607 if (!actions->noncasdemand.blob) {
14608 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14609 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14610 actions->noncasdemand.blob = (char*) (blob + 2);
14611 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14614 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14615 if (!actions->demandchoice.blob) {
14616 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14617 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14618 actions->demandchoice.blob = (char*) (blob + 2);
14619 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14629 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14630 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14632 guint32 idx = mono_metadata_token_index (klass->type_token);
14633 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14634 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14635 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14639 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14640 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14642 guint32 idx = mono_method_get_index (method);
14643 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14644 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14645 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14649 * Collect all actions (that requires to generate code in mini) assigned for
14650 * the specified method.
14651 * Note: Don't use the content of actions if the function return FALSE.
14654 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14656 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14657 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14658 MonoBoolean result = FALSE;
14661 /* quick exit if no declarative security is present in the metadata */
14662 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14665 /* we want the original as the wrapper is "free" of the security informations */
14666 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14667 method = mono_marshal_method_from_wrapper (method);
14672 /* First we look for method-level attributes */
14673 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14674 mono_class_init (method->klass);
14675 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14677 result = mono_declsec_get_method_demands_params (method, demands,
14678 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14681 /* Here we use (or create) the class declarative cache to look for demands */
14682 flags = mono_declsec_flags_from_class (method->klass);
14683 if (flags & mask) {
14685 mono_class_init (method->klass);
14686 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14688 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14689 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14692 /* The boolean return value is used as a shortcut in case nothing needs to
14693 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14699 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14701 * Note: Don't use the content of actions if the function return FALSE.
14704 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14706 MonoBoolean result = FALSE;
14709 /* quick exit if no declarative security is present in the metadata */
14710 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14713 /* we want the original as the wrapper is "free" of the security informations */
14714 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14715 method = mono_marshal_method_from_wrapper (method);
14720 /* results are independant - zeroize both */
14721 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14722 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14724 /* First we look for method-level attributes */
14725 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14726 mono_class_init (method->klass);
14728 result = mono_declsec_get_method_demands_params (method, cmethod,
14729 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14732 /* Here we use (or create) the class declarative cache to look for demands */
14733 flags = mono_declsec_flags_from_class (method->klass);
14734 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14735 mono_class_init (method->klass);
14737 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14738 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14745 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14747 * @klass The inherited class - this is the class that provides the security check (attributes)
14749 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14751 * Note: Don't use the content of actions if the function return FALSE.
14754 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14756 MonoBoolean result = FALSE;
14759 /* quick exit if no declarative security is present in the metadata */
14760 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14763 /* Here we use (or create) the class declarative cache to look for demands */
14764 flags = mono_declsec_flags_from_class (klass);
14765 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14766 mono_class_init (klass);
14767 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14769 result |= mono_declsec_get_class_demands_params (klass, demands,
14770 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14777 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14779 * Note: Don't use the content of actions if the function return FALSE.
14782 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14784 /* quick exit if no declarative security is present in the metadata */
14785 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14788 /* we want the original as the wrapper is "free" of the security informations */
14789 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14790 method = mono_marshal_method_from_wrapper (method);
14795 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14796 mono_class_init (method->klass);
14797 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14799 return mono_declsec_get_method_demands_params (method, demands,
14800 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14807 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14809 guint32 cols [MONO_DECL_SECURITY_SIZE];
14813 int index = mono_metadata_declsec_from_index (image, token);
14817 t = &image->tables [MONO_TABLE_DECLSECURITY];
14818 for (i = index; i < t->rows; i++) {
14819 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14821 /* shortcut - index are ordered */
14822 if (token != cols [MONO_DECL_SECURITY_PARENT])
14825 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14826 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14827 entry->blob = (char*) (metadata + 2);
14828 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14837 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14839 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14840 guint32 idx = mono_method_get_index (method);
14841 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14842 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14843 return get_declsec_action (method->klass->image, idx, action, entry);
14849 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14852 guint32 flags = mono_declsec_flags_from_class (klass);
14853 if (declsec_flags_map [action] & flags) {
14854 guint32 idx = mono_metadata_token_index (klass->type_token);
14855 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14856 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14857 return get_declsec_action (klass->image, idx, action, entry);
14863 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14865 guint32 idx = 1; /* there is only one assembly */
14866 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14867 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14869 return get_declsec_action (assembly->image, idx, action, entry);
14873 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14875 MonoObject *res, *exc;
14877 static MonoMethod *method = NULL;
14879 mono_error_init (error);
14881 if (method == NULL) {
14882 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14887 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14888 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14890 g_assert (mono_class_get_ref_info (klass));
14891 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14893 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14894 return_val_if_nok (error, FALSE);
14896 MonoError inner_error;
14897 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14899 if (exc || !is_ok (&inner_error)) {
14900 mono_error_cleanup (&inner_error);
14903 return *(MonoBoolean*)mono_object_unbox (res);
14907 * mono_reflection_type_get_type:
14908 * @reftype: the System.Type object
14910 * Returns the MonoType* associated with the C# System.Type object @reftype.
14913 mono_reflection_type_get_type (MonoReflectionType *reftype)
14915 g_assert (reftype);
14918 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14919 mono_error_assert_ok (&error);
14924 * mono_reflection_assembly_get_assembly:
14925 * @refassembly: the System.Reflection.Assembly object
14927 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14930 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14932 g_assert (refassembly);
14934 return refassembly->assembly;