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))
1482 int num_attrs = count - not_visible;
1483 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
1485 ainfo->image = image;
1486 ainfo->num_attrs = num_attrs;
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 g_assert (cattr->ctor->method);
1496 ainfo->attrs [index].data = saved;
1497 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1501 g_assert (index == num_attrs && count == num_attrs + not_visible);
1506 #ifndef DISABLE_REFLECTION_EMIT
1508 * LOCKING: Acquires the loader lock.
1511 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1513 MONO_REQ_GC_UNSAFE_MODE;
1515 MonoCustomAttrInfo *ainfo, *tmp;
1517 if (!cattrs || !mono_array_length (cattrs))
1520 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1522 mono_loader_lock ();
1523 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1525 mono_custom_attrs_free (tmp);
1526 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1527 mono_loader_unlock ();
1533 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1535 MONO_REQ_GC_NEUTRAL_MODE;
1537 if (ainfo && !ainfo->cached)
1542 * idx is the table index of the object
1543 * type is one of MONO_CUSTOM_ATTR_*
1546 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1548 MONO_REQ_GC_UNSAFE_MODE;
1550 MonoDynamicTable *table;
1551 MonoReflectionCustomAttr *cattr;
1553 guint32 count, i, token;
1555 char *p = blob_size;
1557 mono_error_init (error);
1559 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1562 count = mono_array_length (cattrs);
1563 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1564 table->rows += count;
1565 alloc_table (table, table->rows);
1566 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1567 idx <<= MONO_CUSTOM_ATTR_BITS;
1569 for (i = 0; i < count; ++i) {
1570 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1571 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1572 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1573 if (!mono_error_ok (error)) goto fail;
1574 type = mono_metadata_token_index (token);
1575 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1576 switch (mono_metadata_token_table (token)) {
1577 case MONO_TABLE_METHOD:
1578 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1580 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1581 * method, not the one returned by mono_image_create_token ().
1583 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1585 case MONO_TABLE_MEMBERREF:
1586 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1589 g_warning ("got wrong token in custom attr");
1592 values [MONO_CUSTOM_ATTR_TYPE] = type;
1594 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1595 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1596 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1597 values += MONO_CUSTOM_ATTR_SIZE;
1608 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1610 MONO_REQ_GC_UNSAFE_MODE;
1612 MonoDynamicTable *table;
1614 guint32 count, i, idx;
1615 MonoReflectionPermissionSet *perm;
1620 count = mono_array_length (permissions);
1621 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1622 table->rows += count;
1623 alloc_table (table, table->rows);
1625 for (i = 0; i < mono_array_length (permissions); ++i) {
1626 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1628 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1630 idx = mono_metadata_token_index (parent_token);
1631 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1632 switch (mono_metadata_token_table (parent_token)) {
1633 case MONO_TABLE_TYPEDEF:
1634 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1636 case MONO_TABLE_METHOD:
1637 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1639 case MONO_TABLE_ASSEMBLY:
1640 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1643 g_assert_not_reached ();
1646 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1647 values [MONO_DECL_SECURITY_PARENT] = idx;
1648 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1655 * Fill in the MethodDef and ParamDef tables for a method.
1656 * This is used for both normal methods and constructors.
1659 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1661 MONO_REQ_GC_UNSAFE_MODE;
1663 MonoDynamicTable *table;
1667 mono_error_init (error);
1669 /* room in this table is already allocated */
1670 table = &assembly->tables [MONO_TABLE_METHOD];
1671 *mb->table_idx = table->next_idx ++;
1672 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1673 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1674 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1675 return_val_if_nok (error, FALSE);
1676 values [MONO_METHOD_FLAGS] = mb->attrs;
1677 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1678 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1679 return_val_if_nok (error, FALSE);
1680 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1681 return_val_if_nok (error, FALSE);
1683 table = &assembly->tables [MONO_TABLE_PARAM];
1684 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1686 mono_image_add_decl_security (assembly,
1687 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1690 MonoDynamicTable *mtable;
1693 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1694 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1697 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1698 if (mono_array_get (mb->pinfo, gpointer, i))
1701 table->rows += count;
1702 alloc_table (table, table->rows);
1703 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1704 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1705 MonoReflectionParamBuilder *pb;
1706 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1707 values [MONO_PARAM_FLAGS] = pb->attrs;
1708 values [MONO_PARAM_SEQUENCE] = i;
1709 if (pb->name != NULL) {
1710 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
1711 return_val_if_nok (error, FALSE);
1713 values [MONO_PARAM_NAME] = 0;
1715 values += MONO_PARAM_SIZE;
1716 if (pb->marshal_info) {
1718 alloc_table (mtable, mtable->rows);
1719 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1720 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1721 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1722 return_val_if_nok (error, FALSE);
1724 pb->table_idx = table->next_idx++;
1725 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1726 guint32 field_type = 0;
1727 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1729 alloc_table (mtable, mtable->rows);
1730 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1731 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1732 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1733 mvalues [MONO_CONSTANT_TYPE] = field_type;
1734 mvalues [MONO_CONSTANT_PADDING] = 0;
1743 #ifndef DISABLE_REFLECTION_EMIT
1745 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1747 MONO_REQ_GC_UNSAFE_MODE;
1749 mono_error_init (error);
1750 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1752 rmb->ilgen = mb->ilgen;
1753 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1754 return_val_if_nok (error, FALSE);
1755 rmb->parameters = mb->parameters;
1756 rmb->generic_params = mb->generic_params;
1757 rmb->generic_container = mb->generic_container;
1758 rmb->opt_types = NULL;
1759 rmb->pinfo = mb->pinfo;
1760 rmb->attrs = mb->attrs;
1761 rmb->iattrs = mb->iattrs;
1762 rmb->call_conv = mb->call_conv;
1763 rmb->code = mb->code;
1764 rmb->type = mb->type;
1765 rmb->name = mb->name;
1766 rmb->table_idx = &mb->table_idx;
1767 rmb->init_locals = mb->init_locals;
1768 rmb->skip_visibility = FALSE;
1769 rmb->return_modreq = mb->return_modreq;
1770 rmb->return_modopt = mb->return_modopt;
1771 rmb->param_modreq = mb->param_modreq;
1772 rmb->param_modopt = mb->param_modopt;
1773 rmb->permissions = mb->permissions;
1774 rmb->mhandle = mb->mhandle;
1779 rmb->charset = mb->charset;
1780 rmb->extra_flags = mb->extra_flags;
1781 rmb->native_cc = mb->native_cc;
1782 rmb->dllentry = mb->dllentry;
1790 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1792 MONO_REQ_GC_UNSAFE_MODE;
1794 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1796 mono_error_init (error);
1798 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1800 rmb->ilgen = mb->ilgen;
1801 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1802 return_val_if_nok (error, FALSE);
1803 rmb->parameters = mb->parameters;
1804 rmb->generic_params = NULL;
1805 rmb->generic_container = NULL;
1806 rmb->opt_types = NULL;
1807 rmb->pinfo = mb->pinfo;
1808 rmb->attrs = mb->attrs;
1809 rmb->iattrs = mb->iattrs;
1810 rmb->call_conv = mb->call_conv;
1812 rmb->type = mb->type;
1813 rmb->name = mono_string_new (mono_domain_get (), name);
1814 rmb->table_idx = &mb->table_idx;
1815 rmb->init_locals = mb->init_locals;
1816 rmb->skip_visibility = FALSE;
1817 rmb->return_modreq = NULL;
1818 rmb->return_modopt = NULL;
1819 rmb->param_modreq = mb->param_modreq;
1820 rmb->param_modopt = mb->param_modopt;
1821 rmb->permissions = mb->permissions;
1822 rmb->mhandle = mb->mhandle;
1830 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1832 MONO_REQ_GC_UNSAFE_MODE;
1834 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1836 rmb->ilgen = mb->ilgen;
1837 rmb->rtype = mb->rtype;
1838 rmb->parameters = mb->parameters;
1839 rmb->generic_params = NULL;
1840 rmb->generic_container = NULL;
1841 rmb->opt_types = NULL;
1843 rmb->attrs = mb->attrs;
1845 rmb->call_conv = mb->call_conv;
1847 rmb->type = (MonoObject *) mb->owner;
1848 rmb->name = mb->name;
1849 rmb->table_idx = NULL;
1850 rmb->init_locals = mb->init_locals;
1851 rmb->skip_visibility = mb->skip_visibility;
1852 rmb->return_modreq = NULL;
1853 rmb->return_modopt = NULL;
1854 rmb->param_modreq = NULL;
1855 rmb->param_modopt = NULL;
1856 rmb->permissions = NULL;
1857 rmb->mhandle = mb->mhandle;
1864 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1866 MONO_REQ_GC_UNSAFE_MODE;
1868 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1869 MonoDynamicTable *table;
1872 MonoReflectionMethod *m;
1875 mono_error_init (error);
1877 if (!mb->override_methods)
1880 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1881 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1883 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1885 alloc_table (table, table->rows);
1886 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1887 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1888 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1890 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1891 return_val_if_nok (error, FALSE);
1893 switch (mono_metadata_token_table (tok)) {
1894 case MONO_TABLE_MEMBERREF:
1895 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1897 case MONO_TABLE_METHOD:
1898 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1901 g_assert_not_reached ();
1903 values [MONO_METHODIMPL_DECLARATION] = tok;
1909 #ifndef DISABLE_REFLECTION_EMIT
1911 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1913 MONO_REQ_GC_UNSAFE_MODE;
1915 MonoDynamicTable *table;
1917 ReflectionMethodBuilder rmb;
1920 mono_error_init (error);
1922 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1923 !mono_image_basic_method (&rmb, assembly, error))
1926 mb->table_idx = *rmb.table_idx;
1928 if (mb->dll) { /* It's a P/Invoke method */
1930 /* map CharSet values to on-disk values */
1931 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1932 int extra_flags = mb->extra_flags;
1933 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1935 alloc_table (table, table->rows);
1936 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1938 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1939 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1941 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
1942 return_val_if_nok (error, FALSE);
1944 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1945 return_val_if_nok (error, FALSE);
1947 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
1948 return_val_if_nok (error, FALSE);
1949 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1950 table = &assembly->tables [MONO_TABLE_MODULEREF];
1952 alloc_table (table, table->rows);
1953 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1954 values [MONO_IMPLMAP_SCOPE] = table->rows;
1958 if (mb->generic_params) {
1959 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1960 table->rows += mono_array_length (mb->generic_params);
1961 alloc_table (table, table->rows);
1962 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1963 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1965 mono_image_get_generic_param_info (
1966 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1974 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1976 MONO_REQ_GC_UNSAFE_MODE;
1978 ReflectionMethodBuilder rmb;
1980 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1983 if (!mono_image_basic_method (&rmb, assembly, error))
1986 mb->table_idx = *rmb.table_idx;
1993 type_get_fully_qualified_name (MonoType *type)
1995 MONO_REQ_GC_NEUTRAL_MODE;
1997 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2001 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
2003 MONO_REQ_GC_UNSAFE_MODE;
2008 klass = mono_class_from_mono_type (type);
2010 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2011 ta = klass->image->assembly;
2012 if (assembly_is_dynamic (ta) || (ta == ass)) {
2013 if (klass->generic_class || klass->generic_container)
2014 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2015 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2017 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2020 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2023 #ifndef DISABLE_REFLECTION_EMIT
2024 /*field_image is the image to which the eventual custom mods have been encoded against*/
2026 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2028 MONO_REQ_GC_NEUTRAL_MODE;
2031 guint32 idx, i, token;
2033 if (!assembly->save)
2036 sigbuffer_init (&buf, 32);
2038 sigbuffer_add_value (&buf, 0x06);
2039 /* encode custom attributes before the type */
2040 if (type->num_mods) {
2041 for (i = 0; i < type->num_mods; ++i) {
2044 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2045 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2047 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2049 token = type->modifiers [i].token;
2052 if (type->modifiers [i].required)
2053 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2055 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2057 sigbuffer_add_value (&buf, token);
2060 encode_type (assembly, type, &buf);
2061 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2062 sigbuffer_free (&buf);
2068 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2070 MONO_REQ_GC_UNSAFE_MODE;
2072 mono_error_init (error);
2076 guint32 typespec = 0;
2080 init_type_builder_generics (fb->type, error);
2081 return_val_if_nok (error, 0);
2083 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2084 return_val_if_nok (error, 0);
2085 klass = mono_class_from_mono_type (type);
2087 sigbuffer_init (&buf, 32);
2089 sigbuffer_add_value (&buf, 0x06);
2090 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2093 /* encode custom attributes before the type */
2095 if (klass->generic_container)
2096 typespec = create_typespec (assembly, type);
2099 MonoGenericClass *gclass;
2100 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2101 encode_generic_class (assembly, gclass, &buf);
2103 encode_type (assembly, type, &buf);
2105 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2106 sigbuffer_free (&buf);
2109 sigbuffer_free (&buf);
2114 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2116 MONO_REQ_GC_UNSAFE_MODE;
2118 char blob_size [64];
2119 char *b = blob_size;
2122 guint32 idx = 0, len = 0, dummy = 0;
2124 buf = (char *)g_malloc (64);
2126 *ret_type = MONO_TYPE_CLASS;
2128 box_val = (char*)&dummy;
2130 box_val = ((char*)val) + sizeof (MonoObject);
2131 *ret_type = val->vtable->klass->byval_arg.type;
2134 switch (*ret_type) {
2135 case MONO_TYPE_BOOLEAN:
2140 case MONO_TYPE_CHAR:
2157 case MONO_TYPE_VALUETYPE: {
2158 MonoClass *klass = val->vtable->klass;
2160 if (klass->enumtype) {
2161 *ret_type = mono_class_enum_basetype (klass)->type;
2163 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2166 g_error ("we can't encode valuetypes, we should have never reached this line");
2169 case MONO_TYPE_CLASS:
2171 case MONO_TYPE_STRING: {
2172 MonoString *str = (MonoString*)val;
2173 /* there is no signature */
2174 len = str->length * 2;
2175 mono_metadata_encode_value (len, b, &b);
2176 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2178 char *swapped = g_malloc (2 * mono_string_length (str));
2179 const char *p = (const char*)mono_string_chars (str);
2181 swap_with_size (swapped, p, 2, mono_string_length (str));
2182 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2186 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2192 case MONO_TYPE_GENERICINST:
2193 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2196 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2199 /* there is no signature */
2200 mono_metadata_encode_value (len, b, &b);
2201 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2202 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2203 swap_with_size (blob_size, box_val, len, 1);
2204 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2206 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2214 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2216 MONO_REQ_GC_UNSAFE_MODE;
2218 mono_error_init (error);
2224 sigbuffer_init (&buf, 32);
2226 sigbuffer_add_value (&buf, minfo->type);
2228 switch (minfo->type) {
2229 case MONO_NATIVE_BYVALTSTR:
2230 case MONO_NATIVE_BYVALARRAY:
2231 sigbuffer_add_value (&buf, minfo->count);
2233 case MONO_NATIVE_LPARRAY:
2234 if (minfo->eltype || minfo->has_size) {
2235 sigbuffer_add_value (&buf, minfo->eltype);
2236 if (minfo->has_size) {
2237 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2238 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2240 /* LAMESPEC: ElemMult is undocumented */
2241 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2245 case MONO_NATIVE_SAFEARRAY:
2247 sigbuffer_add_value (&buf, minfo->eltype);
2249 case MONO_NATIVE_CUSTOM:
2251 str = mono_string_to_utf8_checked (minfo->guid, error);
2252 if (!is_ok (error)) {
2253 sigbuffer_free (&buf);
2257 sigbuffer_add_value (&buf, len);
2258 sigbuffer_add_mem (&buf, str, len);
2261 sigbuffer_add_value (&buf, 0);
2263 /* native type name */
2264 sigbuffer_add_value (&buf, 0);
2265 /* custom marshaler type name */
2266 if (minfo->marshaltype || minfo->marshaltyperef) {
2267 if (minfo->marshaltyperef) {
2268 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2269 if (!is_ok (error)) {
2270 sigbuffer_free (&buf);
2273 str = type_get_fully_qualified_name (marshaltype);
2275 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2276 if (!is_ok (error)) {
2277 sigbuffer_free (&buf);
2282 sigbuffer_add_value (&buf, len);
2283 sigbuffer_add_mem (&buf, str, len);
2286 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2287 sigbuffer_add_value (&buf, 0);
2289 if (minfo->mcookie) {
2290 str = mono_string_to_utf8_checked (minfo->mcookie, error);
2291 if (!is_ok (error)) {
2292 sigbuffer_free (&buf);
2296 sigbuffer_add_value (&buf, len);
2297 sigbuffer_add_mem (&buf, str, len);
2300 sigbuffer_add_value (&buf, 0);
2306 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2307 sigbuffer_free (&buf);
2312 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2314 MONO_REQ_GC_UNSAFE_MODE;
2316 mono_error_init (error);
2318 MonoDynamicTable *table;
2321 /* maybe this fixup should be done in the C# code */
2322 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2323 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2324 table = &assembly->tables [MONO_TABLE_FIELD];
2325 fb->table_idx = table->next_idx ++;
2326 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2327 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2328 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
2329 return_if_nok (error);
2330 values [MONO_FIELD_FLAGS] = fb->attrs;
2331 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2332 return_if_nok (error);
2335 if (fb->offset != -1) {
2336 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2338 alloc_table (table, table->rows);
2339 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2340 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2341 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2343 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2344 MonoTypeEnum field_type = (MonoTypeEnum)0;
2345 table = &assembly->tables [MONO_TABLE_CONSTANT];
2347 alloc_table (table, table->rows);
2348 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2349 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2350 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2351 values [MONO_CONSTANT_TYPE] = field_type;
2352 values [MONO_CONSTANT_PADDING] = 0;
2354 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2356 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2358 alloc_table (table, table->rows);
2359 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2360 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2362 * We store it in the code section because it's simpler for now.
2365 if (mono_array_length (fb->rva_data) >= 10)
2366 stream_data_align (&assembly->code);
2367 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2369 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2370 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2372 if (fb->marshal_info) {
2373 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2375 alloc_table (table, table->rows);
2376 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2377 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2378 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2379 return_if_nok (error);
2384 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2386 MONO_REQ_GC_UNSAFE_MODE;
2388 mono_error_init (error);
2391 guint32 nparams = 0;
2392 MonoReflectionMethodBuilder *mb = fb->get_method;
2393 MonoReflectionMethodBuilder *smb = fb->set_method;
2396 if (mb && mb->parameters)
2397 nparams = mono_array_length (mb->parameters);
2398 if (!mb && smb && smb->parameters)
2399 nparams = mono_array_length (smb->parameters) - 1;
2400 sigbuffer_init (&buf, 32);
2401 if (fb->call_conv & 0x20)
2402 sigbuffer_add_byte (&buf, 0x28);
2404 sigbuffer_add_byte (&buf, 0x08);
2405 sigbuffer_add_value (&buf, nparams);
2407 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2410 for (i = 0; i < nparams; ++i) {
2411 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2412 encode_reflection_type (assembly, pt, &buf, error);
2416 } else if (smb && smb->parameters) {
2417 /* the property type is the last param */
2418 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2422 for (i = 0; i < nparams; ++i) {
2423 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2424 encode_reflection_type (assembly, pt, &buf, error);
2429 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2434 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2435 sigbuffer_free (&buf);
2438 sigbuffer_free (&buf);
2443 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2445 MONO_REQ_GC_UNSAFE_MODE;
2447 mono_error_init (error);
2449 MonoDynamicTable *table;
2451 guint num_methods = 0;
2455 * we need to set things in the following tables:
2456 * PROPERTYMAP (info already filled in _get_type_info ())
2457 * PROPERTY (rows already preallocated in _get_type_info ())
2458 * METHOD (method info already done with the generic method code)
2462 table = &assembly->tables [MONO_TABLE_PROPERTY];
2463 pb->table_idx = table->next_idx ++;
2464 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2465 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
2466 return_if_nok (error);
2467 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2468 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2469 return_if_nok (error);
2472 /* FIXME: we still don't handle 'other' methods */
2473 if (pb->get_method) num_methods ++;
2474 if (pb->set_method) num_methods ++;
2476 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2477 table->rows += num_methods;
2478 alloc_table (table, table->rows);
2480 if (pb->get_method) {
2481 semaidx = table->next_idx ++;
2482 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2483 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2484 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2485 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2487 if (pb->set_method) {
2488 semaidx = table->next_idx ++;
2489 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2490 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2491 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2492 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2494 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2495 MonoTypeEnum field_type = (MonoTypeEnum)0;
2496 table = &assembly->tables [MONO_TABLE_CONSTANT];
2498 alloc_table (table, table->rows);
2499 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2500 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2501 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2502 values [MONO_CONSTANT_TYPE] = field_type;
2503 values [MONO_CONSTANT_PADDING] = 0;
2508 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2510 MONO_REQ_GC_UNSAFE_MODE;
2512 MonoDynamicTable *table;
2514 guint num_methods = 0;
2518 * we need to set things in the following tables:
2519 * EVENTMAP (info already filled in _get_type_info ())
2520 * EVENT (rows already preallocated in _get_type_info ())
2521 * METHOD (method info already done with the generic method code)
2524 table = &assembly->tables [MONO_TABLE_EVENT];
2525 eb->table_idx = table->next_idx ++;
2526 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2527 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
2528 return_if_nok (error);
2529 values [MONO_EVENT_FLAGS] = eb->attrs;
2530 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2531 return_if_nok (error);
2532 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2535 * FIXME: we still don't handle 'other' methods
2537 if (eb->add_method) num_methods ++;
2538 if (eb->remove_method) num_methods ++;
2539 if (eb->raise_method) num_methods ++;
2541 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2542 table->rows += num_methods;
2543 alloc_table (table, table->rows);
2545 if (eb->add_method) {
2546 semaidx = table->next_idx ++;
2547 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2548 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2549 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2550 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2552 if (eb->remove_method) {
2553 semaidx = table->next_idx ++;
2554 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2555 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2556 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2557 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2559 if (eb->raise_method) {
2560 semaidx = table->next_idx ++;
2561 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2562 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2563 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2564 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2569 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2571 MONO_REQ_GC_UNSAFE_MODE;
2573 mono_error_init (error);
2575 MonoDynamicTable *table;
2576 guint32 num_constraints, i;
2580 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2581 num_constraints = gparam->iface_constraints ?
2582 mono_array_length (gparam->iface_constraints) : 0;
2583 table->rows += num_constraints;
2584 if (gparam->base_type)
2586 alloc_table (table, table->rows);
2588 if (gparam->base_type) {
2589 table_idx = table->next_idx ++;
2590 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2592 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2593 return_if_nok (error);
2594 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2595 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2598 for (i = 0; i < num_constraints; i++) {
2599 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2600 gparam->iface_constraints, gpointer, i);
2602 table_idx = table->next_idx ++;
2603 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2605 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2606 return_if_nok (error);
2608 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2609 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2614 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2616 MONO_REQ_GC_UNSAFE_MODE;
2618 GenericParamTableEntry *entry;
2621 * The GenericParam table must be sorted according to the `owner' field.
2622 * We need to do this sorting prior to writing the GenericParamConstraint
2623 * table, since we have to use the final GenericParam table indices there
2624 * and they must also be sorted.
2627 entry = g_new0 (GenericParamTableEntry, 1);
2628 entry->owner = owner;
2629 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2630 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2631 entry->gparam = gparam;
2633 g_ptr_array_add (assembly->gen_params, entry);
2637 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2639 MONO_REQ_GC_UNSAFE_MODE;
2641 MonoDynamicTable *table;
2642 MonoGenericParam *param;
2646 mono_error_init (error);
2648 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2649 table_idx = table->next_idx ++;
2650 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2652 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2653 return_val_if_nok (error, FALSE);
2655 param = gparam_type->data.generic_param;
2657 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2658 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2659 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2660 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2662 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2665 encode_constraints (entry->gparam, table_idx, assembly, error);
2666 return_val_if_nok (error, FALSE);
2672 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2674 MONO_REQ_GC_UNSAFE_MODE;
2676 MonoDynamicTable *table;
2679 guint32 cols [MONO_ASSEMBLY_SIZE];
2683 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2686 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2687 table = &assembly->tables [MONO_TABLE_MODULEREF];
2688 token = table->next_idx ++;
2690 alloc_table (table, table->rows);
2691 values = table->values + token * MONO_MODULEREF_SIZE;
2692 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2694 token <<= MONO_RESOLUTION_SCOPE_BITS;
2695 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2696 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2701 if (assembly_is_dynamic (image->assembly))
2703 memset (cols, 0, sizeof (cols));
2705 /* image->assembly->image is the manifest module */
2706 image = image->assembly->image;
2707 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2710 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2711 token = table->next_idx ++;
2713 alloc_table (table, table->rows);
2714 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2715 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2716 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2717 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2718 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2719 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2720 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2721 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2722 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2724 if (strcmp ("", image->assembly->aname.culture)) {
2725 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2726 image->assembly->aname.culture);
2729 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2730 guchar pubtoken [9];
2732 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2733 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2735 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2737 token <<= MONO_RESOLUTION_SCOPE_BITS;
2738 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2739 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2744 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2746 MONO_REQ_GC_NEUTRAL_MODE;
2748 MonoDynamicTable *table;
2753 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2756 sigbuffer_init (&buf, 32);
2757 switch (type->type) {
2758 case MONO_TYPE_FNPTR:
2760 case MONO_TYPE_SZARRAY:
2761 case MONO_TYPE_ARRAY:
2763 case MONO_TYPE_MVAR:
2764 case MONO_TYPE_GENERICINST:
2765 encode_type (assembly, type, &buf);
2767 case MONO_TYPE_CLASS:
2768 case MONO_TYPE_VALUETYPE: {
2769 MonoClass *k = mono_class_from_mono_type (type);
2770 if (!k || !k->generic_container) {
2771 sigbuffer_free (&buf);
2774 encode_type (assembly, type, &buf);
2778 sigbuffer_free (&buf);
2782 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2783 if (assembly->save) {
2784 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2785 alloc_table (table, table->rows + 1);
2786 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2787 values [MONO_TYPESPEC_SIGNATURE] = token;
2789 sigbuffer_free (&buf);
2791 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2792 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2798 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2800 MONO_REQ_GC_UNSAFE_MODE;
2802 MonoDynamicTable *table;
2804 guint32 token, scope, enclosing;
2807 /* if the type requires a typespec, we must try that first*/
2808 if (try_typespec && (token = create_typespec (assembly, type)))
2810 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2813 klass = mono_class_from_mono_type (type);
2815 klass = mono_class_from_mono_type (type);
2818 * If it's in the same module and not a generic type parameter:
2820 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2821 (type->type != MONO_TYPE_MVAR)) {
2822 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2823 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2824 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2828 if (klass->nested_in) {
2829 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2830 /* get the typeref idx of the enclosing type */
2831 enclosing >>= MONO_TYPEDEFORREF_BITS;
2832 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2834 scope = resolution_scope_from_image (assembly, klass->image);
2836 table = &assembly->tables [MONO_TABLE_TYPEREF];
2837 if (assembly->save) {
2838 alloc_table (table, table->rows + 1);
2839 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2840 values [MONO_TYPEREF_SCOPE] = scope;
2841 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2842 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2844 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2845 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2847 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2852 * Despite the name, we handle also TypeSpec (with the above helper).
2855 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2857 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2860 #ifndef DISABLE_REFLECTION_EMIT
2862 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2864 MONO_REQ_GC_NEUTRAL_MODE;
2866 MonoDynamicTable *table;
2868 guint32 token, pclass;
2870 switch (parent & MONO_TYPEDEFORREF_MASK) {
2871 case MONO_TYPEDEFORREF_TYPEREF:
2872 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2874 case MONO_TYPEDEFORREF_TYPESPEC:
2875 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2877 case MONO_TYPEDEFORREF_TYPEDEF:
2878 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2881 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2884 /* extract the index */
2885 parent >>= MONO_TYPEDEFORREF_BITS;
2887 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2889 if (assembly->save) {
2890 alloc_table (table, table->rows + 1);
2891 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2892 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2893 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2894 values [MONO_MEMBERREF_SIGNATURE] = sig;
2897 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2904 * Insert a memberef row into the metadata: the token that point to the memberref
2905 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2906 * mono_image_get_fieldref_token()).
2907 * The sig param is an index to an already built signature.
2910 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2912 MONO_REQ_GC_NEUTRAL_MODE;
2914 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2915 return mono_image_add_memberef_row (assembly, parent, name, sig);
2920 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2922 MONO_REQ_GC_NEUTRAL_MODE;
2925 MonoMethodSignature *sig;
2927 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2929 if (create_typespec) {
2930 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2935 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2936 if (token && !create_typespec)
2939 g_assert (!method->is_inflated);
2942 * A methodref signature can't contain an unmanaged calling convention.
2944 sig = mono_metadata_signature_dup (mono_method_signature (method));
2945 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2946 sig->call_convention = MONO_CALL_DEFAULT;
2947 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2948 method->name, method_encode_signature (assembly, sig));
2950 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2953 if (create_typespec) {
2954 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2955 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2956 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2958 if (assembly->save) {
2961 alloc_table (table, table->rows + 1);
2962 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2963 values [MONO_METHODSPEC_METHOD] = token;
2964 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2967 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2969 /*methodspec and memberef tokens are diferent, */
2970 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2977 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2979 guint32 token, parent, sig;
2980 ReflectionMethodBuilder rmb;
2981 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2983 mono_error_init (error);
2984 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2988 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2992 * A methodref signature can't contain an unmanaged calling convention.
2993 * Since some flags are encoded as part of call_conv, we need to check against it.
2995 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2996 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2998 sig = method_builder_encode_signature (assembly, &rmb, error);
2999 return_val_if_nok (error, 0);
3001 if (tb->generic_params) {
3002 parent = create_generic_typespec (assembly, tb, error);
3003 return_val_if_nok (error, 0);
3005 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
3006 return_val_if_nok (error, 0);
3008 parent = mono_image_typedef_or_ref (assembly, t);
3011 char *name = mono_string_to_utf8_checked (method->name, error);
3012 return_val_if_nok (error, 0);
3014 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3017 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3023 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3024 const gchar *name, guint32 sig)
3026 MonoDynamicTable *table;
3030 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3032 if (assembly->save) {
3033 alloc_table (table, table->rows + 1);
3034 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3035 values [MONO_MEMBERREF_CLASS] = original;
3036 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3037 values [MONO_MEMBERREF_SIGNATURE] = sig;
3040 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3047 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3051 guint32 nparams = mono_array_length (mb->generic_params);
3054 if (!assembly->save)
3057 sigbuffer_init (&buf, 32);
3059 sigbuffer_add_value (&buf, 0xa);
3060 sigbuffer_add_value (&buf, nparams);
3062 for (i = 0; i < nparams; i++) {
3063 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3064 sigbuffer_add_value (&buf, i);
3067 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3068 sigbuffer_free (&buf);
3073 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3075 MonoDynamicTable *table;
3077 guint32 token, mtoken = 0;
3079 mono_error_init (error);
3080 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3084 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3086 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3087 if (!mono_error_ok (error))
3090 switch (mono_metadata_token_table (mtoken)) {
3091 case MONO_TABLE_MEMBERREF:
3092 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3094 case MONO_TABLE_METHOD:
3095 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3098 g_assert_not_reached ();
3101 if (assembly->save) {
3102 alloc_table (table, table->rows + 1);
3103 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3104 values [MONO_METHODSPEC_METHOD] = mtoken;
3105 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3108 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3111 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3116 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3120 mono_error_init (error);
3122 if (mb->generic_params && create_methodspec)
3123 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3125 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3129 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3130 if (!mono_error_ok (error))
3132 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3137 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3139 guint32 token, parent, sig;
3140 ReflectionMethodBuilder rmb;
3142 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3144 mono_error_init (error);
3146 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3150 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3153 if (tb->generic_params) {
3154 parent = create_generic_typespec (assembly, tb, error);
3155 return_val_if_nok (error, 0);
3157 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3158 return_val_if_nok (error, 0);
3159 parent = mono_image_typedef_or_ref (assembly, type);
3162 name = mono_string_to_utf8_checked (rmb.name, error);
3163 return_val_if_nok (error, 0);
3164 sig = method_builder_encode_signature (assembly, &rmb, error);
3165 return_val_if_nok (error, 0);
3167 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3170 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3176 is_field_on_inst (MonoClassField *field)
3178 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3182 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3185 get_field_on_inst_generic_type (MonoClassField *field)
3187 MonoClass *klass, *gtd;
3188 MonoDynamicGenericClass *dgclass;
3191 g_assert (is_field_on_inst (field));
3193 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3195 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3196 field_index = field - dgclass->fields;
3197 return dgclass->field_generic_types [field_index];
3200 klass = field->parent;
3201 gtd = klass->generic_class->container_class;
3203 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3204 field_index = field - klass->fields;
3205 return gtd->fields [field_index].type;
3208 g_assert_not_reached ();
3212 #ifndef DISABLE_REFLECTION_EMIT
3214 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3220 g_assert (field->parent);
3222 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3226 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3227 int index = field - field->parent->fields;
3228 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3230 if (is_field_on_inst (field))
3231 type = get_field_on_inst_generic_type (field);
3233 type = mono_field_get_type (field);
3235 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3236 mono_field_get_name (field),
3237 fieldref_encode_signature (assembly, field->parent->image, type));
3238 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3243 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3247 MonoGenericClass *gclass;
3251 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3254 if (is_sre_field_builder (mono_object_class (f->fb))) {
3255 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3256 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3257 return_val_if_nok (error, 0);
3258 klass = mono_class_from_mono_type (type);
3259 gclass = type->data.generic_class;
3260 g_assert (gclass->is_dynamic);
3262 guint32 sig_token = field_encode_signature (assembly, fb, error);
3263 return_val_if_nok (error, 0);
3264 name = mono_string_to_utf8_checked (fb->name, error);
3265 return_val_if_nok (error, 0);
3266 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3268 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3270 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3272 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3273 return_val_if_nok (error, 0);
3274 klass = mono_class_from_mono_type (type);
3276 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3277 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3279 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3280 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3283 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3288 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3292 MonoGenericClass *gclass;
3295 mono_error_init (error);
3297 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3299 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3303 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3304 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3305 ReflectionMethodBuilder rmb;
3308 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3309 return_val_if_nok (error, 0);
3310 klass = mono_class_from_mono_type (type);
3312 gclass = type->data.generic_class;
3313 g_assert (gclass->is_dynamic);
3315 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3318 sig = method_builder_encode_signature (assembly, &rmb, error);
3319 return_val_if_nok (error, 0);
3321 name = mono_string_to_utf8_checked (rmb.name, error);
3322 return_val_if_nok (error, 0);
3324 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3326 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3327 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3329 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3330 return_val_if_nok (error, 0);
3331 klass = mono_class_from_mono_type (type);
3333 sig = method_encode_signature (assembly, mono_method_signature (mm));
3334 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3336 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3337 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3341 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3346 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3349 MonoGenericContext tmp_context;
3350 MonoType **type_argv;
3351 MonoGenericInst *ginst;
3352 MonoMethod *method, *inflated;
3355 mono_error_init (error);
3357 init_type_builder_generics ((MonoObject*)m->inst, error);
3358 return_val_if_nok (error, NULL);
3360 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3361 return_val_if_nok (error, NULL);
3363 klass = method->klass;
3365 if (m->method_args == NULL)
3368 if (method->is_inflated)
3369 method = ((MonoMethodInflated *) method)->declaring;
3371 count = mono_array_length (m->method_args);
3373 type_argv = g_new0 (MonoType *, count);
3374 for (i = 0; i < count; i++) {
3375 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3376 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3377 return_val_if_nok (error, NULL);
3379 ginst = mono_metadata_get_generic_inst (count, type_argv);
3382 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3383 tmp_context.method_inst = ginst;
3385 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3386 mono_error_assert_ok (error);
3391 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3393 guint32 sig, token = 0;
3397 mono_error_init (error);
3399 if (m->method_args) {
3400 MonoMethod *inflated;
3402 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3403 return_val_if_nok (error, 0);
3405 if (create_methodspec)
3406 token = mono_image_get_methodspec_token (assembly, inflated);
3408 token = mono_image_get_inflated_method_token (assembly, inflated);
3412 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3416 if (is_sre_method_builder (mono_object_class (m->mb))) {
3417 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3418 MonoGenericClass *gclass;
3419 ReflectionMethodBuilder rmb;
3422 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3423 return_val_if_nok (error, 0);
3424 klass = mono_class_from_mono_type (type);
3425 gclass = type->data.generic_class;
3426 g_assert (gclass->is_dynamic);
3428 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3431 sig = method_builder_encode_signature (assembly, &rmb, error);
3432 return_val_if_nok (error, 0);
3434 name = mono_string_to_utf8_checked (rmb.name, error);
3435 return_val_if_nok (error, 0);
3437 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3439 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3440 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3442 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3443 return_val_if_nok (error, 0);
3444 klass = mono_class_from_mono_type (type);
3446 sig = method_encode_signature (assembly, mono_method_signature (mm));
3447 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3449 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3450 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3453 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3458 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3462 guint32 nparams = context->method_inst->type_argc;
3465 if (!assembly->save)
3468 sigbuffer_init (&buf, 32);
3470 * FIXME: vararg, explicit_this, differenc call_conv values...
3472 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3473 sigbuffer_add_value (&buf, nparams);
3475 for (i = 0; i < nparams; i++)
3476 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3478 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3479 sigbuffer_free (&buf);
3484 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3486 MonoDynamicTable *table;
3488 guint32 token, mtoken = 0, sig;
3489 MonoMethodInflated *imethod;
3490 MonoMethod *declaring;
3492 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3494 g_assert (method->is_inflated);
3495 imethod = (MonoMethodInflated *) method;
3496 declaring = imethod->declaring;
3498 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3499 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3501 if (!mono_method_signature (declaring)->generic_param_count)
3504 switch (mono_metadata_token_table (mtoken)) {
3505 case MONO_TABLE_MEMBERREF:
3506 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3508 case MONO_TABLE_METHOD:
3509 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3512 g_assert_not_reached ();
3515 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3517 if (assembly->save) {
3518 alloc_table (table, table->rows + 1);
3519 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3520 values [MONO_METHODSPEC_METHOD] = mtoken;
3521 values [MONO_METHODSPEC_SIGNATURE] = sig;
3524 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3531 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3533 MonoMethodInflated *imethod;
3536 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3540 g_assert (method->is_inflated);
3541 imethod = (MonoMethodInflated *) method;
3543 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3544 token = method_encode_methodspec (assembly, method);
3546 guint32 sig = method_encode_signature (
3547 assembly, mono_method_signature (imethod->declaring));
3548 token = mono_image_get_memberref_token (
3549 assembly, &method->klass->byval_arg, method->name, sig);
3552 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3557 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3559 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3562 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3563 token = mono_image_get_memberref_token (
3564 assembly, &m->klass->byval_arg, m->name, sig);
3570 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3572 MonoDynamicTable *table;
3581 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3582 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3583 * Because of this, we must not insert it into the `typeref' hash table.
3585 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3586 return_val_if_nok (error, 0);
3587 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3591 sigbuffer_init (&buf, 32);
3593 g_assert (tb->generic_params);
3594 klass = mono_class_from_mono_type (type);
3596 if (tb->generic_container) {
3597 if (!mono_reflection_create_generic_class (tb, error))
3601 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3602 g_assert (klass->generic_container);
3603 sigbuffer_add_value (&buf, klass->byval_arg.type);
3604 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3606 count = mono_array_length (tb->generic_params);
3607 sigbuffer_add_value (&buf, count);
3608 for (i = 0; i < count; i++) {
3609 MonoReflectionGenericParam *gparam;
3611 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3612 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3616 encode_type (assembly, gparam_type, &buf);
3619 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3621 if (assembly->save) {
3622 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3623 alloc_table (table, table->rows + 1);
3624 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3625 values [MONO_TYPESPEC_SIGNATURE] = token;
3627 sigbuffer_free (&buf);
3629 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3630 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3634 sigbuffer_free (&buf);
3639 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3642 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3644 int i, count, len, pos;
3647 mono_error_init (error);
3651 count += mono_array_length (modreq);
3653 count += mono_array_length (modopt);
3656 return mono_metadata_type_dup (NULL, type);
3658 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3659 t = (MonoType *)g_malloc (len);
3660 memcpy (t, type, MONO_SIZEOF_TYPE);
3662 t->num_mods = count;
3665 for (i = 0; i < mono_array_length (modreq); ++i) {
3666 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3669 t->modifiers [pos].required = 1;
3670 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3675 for (i = 0; i < mono_array_length (modopt); ++i) {
3676 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3679 t->modifiers [pos].required = 0;
3680 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3692 init_type_builder_generics (MonoObject *type, MonoError *error)
3694 MonoReflectionTypeBuilder *tb;
3696 mono_error_init (error);
3698 if (!is_sre_type_builder(mono_object_class (type)))
3700 tb = (MonoReflectionTypeBuilder *)type;
3702 if (tb && tb->generic_container)
3703 mono_reflection_create_generic_class (tb, error);
3707 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3709 MonoDynamicTable *table;
3710 MonoType *custom = NULL, *type;
3712 guint32 token, pclass, parent, sig;
3715 mono_error_init (error);
3717 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3721 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3722 return_val_if_nok (error, 0);
3723 /* FIXME: is this call necessary? */
3724 mono_class_from_mono_type (typeb);
3726 /*FIXME this is one more layer of ugliness due how types are created.*/
3727 init_type_builder_generics (fb->type, error);
3728 return_val_if_nok (error, 0);
3730 /* fb->type does not include the custom modifiers */
3731 /* FIXME: We should do this in one place when a fieldbuilder is created */
3732 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3733 return_val_if_nok (error, 0);
3735 if (fb->modreq || fb->modopt) {
3736 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3737 return_val_if_nok (error, 0);
3740 sig = fieldref_encode_signature (assembly, NULL, type);
3743 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3744 return_val_if_nok (error, 0);
3745 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3747 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3748 parent >>= MONO_TYPEDEFORREF_BITS;
3750 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3752 name = mono_string_to_utf8_checked (fb->name, error);
3753 return_val_if_nok (error, 0);
3755 if (assembly->save) {
3756 alloc_table (table, table->rows + 1);
3757 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3758 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3759 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3760 values [MONO_MEMBERREF_SIGNATURE] = sig;
3763 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3765 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3771 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3777 mono_error_init (error);
3779 if (!assembly->save)
3782 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3783 g_assert (helper->type == 2);
3785 if (helper->arguments)
3786 nargs = mono_array_length (helper->arguments);
3790 sigbuffer_init (&buf, 32);
3792 /* Encode calling convention */
3793 /* Change Any to Standard */
3794 if ((helper->call_conv & 0x03) == 0x03)
3795 helper->call_conv = 0x01;
3796 /* explicit_this implies has_this */
3797 if (helper->call_conv & 0x40)
3798 helper->call_conv &= 0x20;
3800 if (helper->call_conv == 0) { /* Unmanaged */
3801 idx = helper->unmanaged_call_conv - 1;
3804 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3805 if (helper->call_conv & 0x02) /* varargs */
3809 sigbuffer_add_byte (&buf, idx);
3810 sigbuffer_add_value (&buf, nargs);
3811 encode_reflection_type (assembly, helper->return_type, &buf, error);
3814 for (i = 0; i < nargs; ++i) {
3815 MonoArray *modreqs = NULL;
3816 MonoArray *modopts = NULL;
3817 MonoReflectionType *pt;
3819 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3820 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3821 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3822 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3824 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3827 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3828 encode_reflection_type (assembly, pt, &buf, error);
3832 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3833 sigbuffer_free (&buf);
3837 sigbuffer_free (&buf);
3842 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3845 MonoDynamicTable *table;
3848 mono_error_init (error);
3850 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3851 idx = table->next_idx ++;
3853 alloc_table (table, table->rows);
3854 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3856 values [MONO_STAND_ALONE_SIGNATURE] =
3857 mono_reflection_encode_sighelper (assembly, helper, error);
3858 return_val_if_nok (error, 0);
3864 reflection_cc_to_file (int call_conv) {
3865 switch (call_conv & 0x3) {
3867 case 1: return MONO_CALL_DEFAULT;
3868 case 2: return MONO_CALL_VARARG;
3870 g_assert_not_reached ();
3874 #endif /* !DISABLE_REFLECTION_EMIT */
3878 MonoMethodSignature *sig;
3883 #ifndef DISABLE_REFLECTION_EMIT
3885 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3890 MonoMethodSignature *sig;
3891 ArrayMethod *am = NULL;
3894 mono_error_init (error);
3896 nparams = mono_array_length (m->parameters);
3897 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3899 sig->sentinelpos = -1;
3900 sig->call_convention = reflection_cc_to_file (m->call_conv);
3901 sig->param_count = nparams;
3903 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3907 sig->ret = &mono_defaults.void_class->byval_arg;
3909 mtype = mono_reflection_type_get_handle (m->parent, error);
3913 for (i = 0; i < nparams; ++i) {
3914 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3919 name = mono_string_to_utf8_checked (m->name, error);
3922 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3923 am = (ArrayMethod *)tmp->data;
3924 if (strcmp (name, am->name) == 0 &&
3925 mono_metadata_type_equal (am->parent, mtype) &&
3926 mono_metadata_signature_equal (am->sig, sig)) {
3929 m->table_idx = am->token & 0xffffff;
3933 am = g_new0 (ArrayMethod, 1);
3937 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3938 method_encode_signature (assembly, sig));
3939 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3940 m->table_idx = am->token & 0xffffff;
3951 * Insert into the metadata tables all the info about the TypeBuilder tb.
3952 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3955 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3957 MonoDynamicTable *table;
3959 int i, is_object = 0, is_system = 0;
3962 mono_error_init (error);
3964 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3965 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3966 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3967 n = mono_string_to_utf8_checked (tb->name, error);
3968 return_val_if_nok (error, FALSE);
3969 if (strcmp (n, "Object") == 0)
3971 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3973 n = mono_string_to_utf8_checked (tb->nspace, error);
3974 return_val_if_nok (error, FALSE);
3975 if (strcmp (n, "System") == 0)
3977 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3979 if (tb->parent && !(is_system && is_object) &&
3980 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3981 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3982 return_val_if_nok (error, FALSE);
3983 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3985 values [MONO_TYPEDEF_EXTENDS] = 0;
3987 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3988 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3991 * if we have explicitlayout or sequentiallayouts, output data in the
3992 * ClassLayout table.
3994 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3995 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3996 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3998 alloc_table (table, table->rows);
3999 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
4000 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
4001 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
4002 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
4005 /* handle interfaces */
4006 if (tb->interfaces) {
4007 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4009 table->rows += mono_array_length (tb->interfaces);
4010 alloc_table (table, table->rows);
4011 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4012 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4013 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4014 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4015 return_val_if_nok (error, FALSE);
4016 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4017 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4018 values += MONO_INTERFACEIMPL_SIZE;
4024 table = &assembly->tables [MONO_TABLE_FIELD];
4025 table->rows += tb->num_fields;
4026 alloc_table (table, table->rows);
4027 for (i = 0; i < tb->num_fields; ++i) {
4028 mono_image_get_field_info (
4029 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4030 return_val_if_nok (error, FALSE);
4034 /* handle constructors */
4036 table = &assembly->tables [MONO_TABLE_METHOD];
4037 table->rows += mono_array_length (tb->ctors);
4038 alloc_table (table, table->rows);
4039 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4040 if (!mono_image_get_ctor_info (domain,
4041 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4047 /* handle methods */
4049 table = &assembly->tables [MONO_TABLE_METHOD];
4050 table->rows += tb->num_methods;
4051 alloc_table (table, table->rows);
4052 for (i = 0; i < tb->num_methods; ++i) {
4053 if (!mono_image_get_method_info (
4054 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4059 /* Do the same with properties etc.. */
4060 if (tb->events && mono_array_length (tb->events)) {
4061 table = &assembly->tables [MONO_TABLE_EVENT];
4062 table->rows += mono_array_length (tb->events);
4063 alloc_table (table, table->rows);
4064 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4066 alloc_table (table, table->rows);
4067 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4068 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4069 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4070 for (i = 0; i < mono_array_length (tb->events); ++i) {
4071 mono_image_get_event_info (
4072 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4073 return_val_if_nok (error, FALSE);
4076 if (tb->properties && mono_array_length (tb->properties)) {
4077 table = &assembly->tables [MONO_TABLE_PROPERTY];
4078 table->rows += mono_array_length (tb->properties);
4079 alloc_table (table, table->rows);
4080 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4082 alloc_table (table, table->rows);
4083 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4084 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4085 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4086 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4087 mono_image_get_property_info (
4088 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4089 return_val_if_nok (error, FALSE);
4093 /* handle generic parameters */
4094 if (tb->generic_params) {
4095 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4096 table->rows += mono_array_length (tb->generic_params);
4097 alloc_table (table, table->rows);
4098 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4099 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4101 mono_image_get_generic_param_info (
4102 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4106 mono_image_add_decl_security (assembly,
4107 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4110 MonoDynamicTable *ntable;
4112 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4113 ntable->rows += mono_array_length (tb->subtypes);
4114 alloc_table (ntable, ntable->rows);
4115 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4117 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4118 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4120 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4121 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4122 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4123 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4124 mono_string_to_utf8 (tb->name), tb->table_idx,
4125 ntable->next_idx, ntable->rows);*/
4126 values += MONO_NESTED_CLASS_SIZE;
4136 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4140 mono_ptr_array_append (*types, type);
4142 if (!type->subtypes)
4145 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4146 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4147 collect_types (types, subtype);
4152 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4154 if ((*type1)->table_idx < (*type2)->table_idx)
4157 if ((*type1)->table_idx > (*type2)->table_idx)
4164 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4167 mono_error_init (error);
4170 for (i = 0; i < mono_array_length (pinfo); ++i) {
4171 MonoReflectionParamBuilder *pb;
4172 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4175 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4183 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4186 mono_error_init (error);
4188 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4191 for (i = 0; i < tb->num_fields; ++i) {
4192 MonoReflectionFieldBuilder* fb;
4193 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4194 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4199 for (i = 0; i < mono_array_length (tb->events); ++i) {
4200 MonoReflectionEventBuilder* eb;
4201 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4202 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4206 if (tb->properties) {
4207 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4208 MonoReflectionPropertyBuilder* pb;
4209 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4210 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4215 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4216 MonoReflectionCtorBuilder* cb;
4217 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4218 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4219 !params_add_cattrs (assembly, cb->pinfo, error))
4225 for (i = 0; i < tb->num_methods; ++i) {
4226 MonoReflectionMethodBuilder* mb;
4227 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4228 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4229 !params_add_cattrs (assembly, mb->pinfo, error))
4235 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4236 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4245 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4249 mono_error_init (error);
4251 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4254 if (moduleb->global_methods) {
4255 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4256 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4257 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4258 !params_add_cattrs (assembly, mb->pinfo, error))
4263 if (moduleb->global_fields) {
4264 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4265 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4266 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4271 if (moduleb->types) {
4272 for (i = 0; i < moduleb->num_types; ++i) {
4273 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4282 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
4284 MonoDynamicTable *table;
4288 char *b = blob_size;
4291 mono_error_init (error);
4293 table = &assembly->tables [MONO_TABLE_FILE];
4295 alloc_table (table, table->rows);
4296 values = table->values + table->next_idx * MONO_FILE_SIZE;
4297 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4298 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4299 if (image_is_dynamic (module->image)) {
4300 /* This depends on the fact that the main module is emitted last */
4301 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
4302 return_val_if_nok (error, FALSE);
4303 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4306 path = g_strdup (module->image->name);
4308 mono_sha1_get_digest_from_file (path, hash);
4311 mono_metadata_encode_value (20, b, &b);
4312 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4313 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4319 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
4321 MonoDynamicTable *table;
4324 mono_error_init (error);
4326 table = &assembly->tables [MONO_TABLE_MODULE];
4327 mb->table_idx = table->next_idx ++;
4328 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
4329 return_if_nok (error);
4330 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4333 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4334 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4335 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4336 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4340 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4341 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4343 MonoDynamicTable *table;
4347 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4348 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4351 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4353 alloc_table (table, table->rows);
4354 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4356 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4357 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4358 if (klass->nested_in)
4359 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4361 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4362 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4363 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4365 res = table->next_idx;
4369 /* Emit nested types */
4370 if (klass->ext && klass->ext->nested_classes) {
4373 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4374 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4381 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4382 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4388 mono_error_init (error);
4390 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4391 return_if_nok (error);
4393 klass = mono_class_from_mono_type (t);
4395 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4397 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4398 parent_index, assembly);
4402 * We need to do this ourselves since klass->nested_classes is not set up.
4405 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4406 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4407 return_if_nok (error);
4413 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4414 guint32 module_index, MonoDynamicImage *assembly)
4416 MonoImage *image = module->image;
4420 t = &image->tables [MONO_TABLE_TYPEDEF];
4422 for (i = 0; i < t->rows; ++i) {
4424 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4425 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4427 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4428 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4433 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4435 MonoDynamicTable *table;
4437 guint32 scope, scope_idx, impl, current_idx;
4438 gboolean forwarder = TRUE;
4439 gpointer iter = NULL;
4442 if (klass->nested_in) {
4443 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4446 scope = resolution_scope_from_image (assembly, klass->image);
4447 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4448 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4449 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4452 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4455 alloc_table (table, table->rows);
4456 current_idx = table->next_idx;
4457 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4459 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4460 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4461 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4462 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4463 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4467 while ((nested = mono_class_get_nested_types (klass, &iter)))
4468 add_exported_type (assemblyb, assembly, nested, current_idx);
4472 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4478 if (!assemblyb->type_forwarders)
4481 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4482 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4487 type = mono_reflection_type_get_handle (t, &error);
4488 mono_error_assert_ok (&error);
4491 klass = mono_class_from_mono_type (type);
4493 add_exported_type (assemblyb, assembly, klass, 0);
4497 #define align_pointer(base,p)\
4499 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4501 (p) += 4 - (__diff & 3);\
4505 compare_constants (const void *a, const void *b)
4507 const guint32 *a_values = (const guint32 *)a;
4508 const guint32 *b_values = (const guint32 *)b;
4509 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4513 compare_semantics (const void *a, const void *b)
4515 const guint32 *a_values = (const guint32 *)a;
4516 const guint32 *b_values = (const guint32 *)b;
4517 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4520 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4524 compare_custom_attrs (const void *a, const void *b)
4526 const guint32 *a_values = (const guint32 *)a;
4527 const guint32 *b_values = (const guint32 *)b;
4529 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4533 compare_field_marshal (const void *a, const void *b)
4535 const guint32 *a_values = (const guint32 *)a;
4536 const guint32 *b_values = (const guint32 *)b;
4538 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4542 compare_nested (const void *a, const void *b)
4544 const guint32 *a_values = (const guint32 *)a;
4545 const guint32 *b_values = (const guint32 *)b;
4547 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4551 compare_genericparam (const void *a, const void *b)
4554 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4555 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4557 if ((*b_entry)->owner == (*a_entry)->owner) {
4558 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4559 mono_error_assert_ok (&error);
4560 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4561 mono_error_assert_ok (&error);
4563 mono_type_get_generic_param_num (a_type) -
4564 mono_type_get_generic_param_num (b_type);
4566 return (*a_entry)->owner - (*b_entry)->owner;
4570 compare_declsecurity_attrs (const void *a, const void *b)
4572 const guint32 *a_values = (const guint32 *)a;
4573 const guint32 *b_values = (const guint32 *)b;
4575 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4579 compare_interface_impl (const void *a, const void *b)
4581 const guint32 *a_values = (const guint32 *)a;
4582 const guint32 *b_values = (const guint32 *)b;
4584 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4588 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4592 pad_heap (MonoDynamicStream *sh)
4594 if (sh->index & 3) {
4595 int sz = 4 - (sh->index & 3);
4596 memset (sh->data + sh->index, 0, sz);
4603 MonoDynamicStream *stream;
4607 * build_compressed_metadata() fills in the blob of data that represents the
4608 * raw metadata as it will be saved in the PE file. The five streams are output
4609 * and the metadata tables are comnpressed from the guint32 array representation,
4610 * to the compressed on-disk format.
4613 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4615 MonoDynamicTable *table;
4617 guint64 valid_mask = 0;
4618 guint64 sorted_mask;
4619 guint32 heapt_size = 0;
4620 guint32 meta_size = 256; /* allow for header and other stuff */
4621 guint32 table_offset;
4622 guint32 ntables = 0;
4628 struct StreamDesc stream_desc [5];
4630 mono_error_init (error);
4632 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4633 for (i = 0; i < assembly->gen_params->len; i++) {
4634 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4635 if (!write_generic_param_entry (assembly, entry, error))
4639 stream_desc [0].name = "#~";
4640 stream_desc [0].stream = &assembly->tstream;
4641 stream_desc [1].name = "#Strings";
4642 stream_desc [1].stream = &assembly->sheap;
4643 stream_desc [2].name = "#US";
4644 stream_desc [2].stream = &assembly->us;
4645 stream_desc [3].name = "#Blob";
4646 stream_desc [3].stream = &assembly->blob;
4647 stream_desc [4].name = "#GUID";
4648 stream_desc [4].stream = &assembly->guid;
4650 /* tables that are sorted */
4651 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4652 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4653 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4654 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4655 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4656 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4657 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4659 /* Compute table sizes */
4660 /* the MonoImage has already been created in mono_image_basic_init() */
4661 meta = &assembly->image;
4663 /* sizes should be multiple of 4 */
4664 pad_heap (&assembly->blob);
4665 pad_heap (&assembly->guid);
4666 pad_heap (&assembly->sheap);
4667 pad_heap (&assembly->us);
4669 /* Setup the info used by compute_sizes () */
4670 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4671 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4672 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4674 meta_size += assembly->blob.index;
4675 meta_size += assembly->guid.index;
4676 meta_size += assembly->sheap.index;
4677 meta_size += assembly->us.index;
4679 for (i=0; i < MONO_TABLE_NUM; ++i)
4680 meta->tables [i].rows = assembly->tables [i].rows;
4682 for (i = 0; i < MONO_TABLE_NUM; i++){
4683 if (meta->tables [i].rows == 0)
4685 valid_mask |= (guint64)1 << i;
4687 meta->tables [i].row_size = mono_metadata_compute_size (
4688 meta, i, &meta->tables [i].size_bitfield);
4689 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4691 heapt_size += 24; /* #~ header size */
4692 heapt_size += ntables * 4;
4693 /* make multiple of 4 */
4696 meta_size += heapt_size;
4697 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4698 p = (unsigned char*)meta->raw_metadata;
4699 /* the metadata signature */
4700 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4701 /* version numbers and 4 bytes reserved */
4702 int16val = (guint16*)p;
4703 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4704 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4706 /* version string */
4707 int32val = (guint32*)p;
4708 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4710 memcpy (p, meta->version, strlen (meta->version));
4711 p += GUINT32_FROM_LE (*int32val);
4712 align_pointer (meta->raw_metadata, p);
4713 int16val = (guint16*)p;
4714 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4715 *int16val = GUINT16_TO_LE (5); /* number of streams */
4719 * write the stream info.
4721 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4722 table_offset += 3; table_offset &= ~3;
4724 assembly->tstream.index = heapt_size;
4725 for (i = 0; i < 5; ++i) {
4726 int32val = (guint32*)p;
4727 stream_desc [i].stream->offset = table_offset;
4728 *int32val++ = GUINT32_TO_LE (table_offset);
4729 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4730 table_offset += GUINT32_FROM_LE (*int32val);
4731 table_offset += 3; table_offset &= ~3;
4733 strcpy ((char*)p, stream_desc [i].name);
4734 p += strlen (stream_desc [i].name) + 1;
4735 align_pointer (meta->raw_metadata, p);
4738 * now copy the data, the table stream header and contents goes first.
4740 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4741 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4742 int32val = (guint32*)p;
4743 *int32val = GUINT32_TO_LE (0); /* reserved */
4746 *p++ = 2; /* version */
4749 if (meta->idx_string_wide)
4751 if (meta->idx_guid_wide)
4753 if (meta->idx_blob_wide)
4756 *p++ = 1; /* reserved */
4757 int64val = (guint64*)p;
4758 *int64val++ = GUINT64_TO_LE (valid_mask);
4759 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4761 int32val = (guint32*)p;
4762 for (i = 0; i < MONO_TABLE_NUM; i++){
4763 if (meta->tables [i].rows == 0)
4765 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4767 p = (unsigned char*)int32val;
4769 /* sort the tables that still need sorting */
4770 table = &assembly->tables [MONO_TABLE_CONSTANT];
4772 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4773 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4775 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4776 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4778 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4779 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4781 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4782 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4784 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4785 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4786 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4788 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4789 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4791 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4793 /* compress the tables */
4794 for (i = 0; i < MONO_TABLE_NUM; i++){
4797 guint32 bitfield = meta->tables [i].size_bitfield;
4798 if (!meta->tables [i].rows)
4800 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4801 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4802 meta->tables [i].base = (char*)p;
4803 for (row = 1; row <= meta->tables [i].rows; ++row) {
4804 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4805 for (col = 0; col < assembly->tables [i].columns; ++col) {
4806 switch (mono_metadata_table_size (bitfield, col)) {
4808 *p++ = values [col];
4811 *p++ = values [col] & 0xff;
4812 *p++ = (values [col] >> 8) & 0xff;
4815 *p++ = values [col] & 0xff;
4816 *p++ = (values [col] >> 8) & 0xff;
4817 *p++ = (values [col] >> 16) & 0xff;
4818 *p++ = (values [col] >> 24) & 0xff;
4821 g_assert_not_reached ();
4825 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4828 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4829 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4830 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4831 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4832 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4834 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4840 * Some tables in metadata need to be sorted according to some criteria, but
4841 * when methods and fields are first created with reflection, they may be assigned a token
4842 * that doesn't correspond to the final token they will get assigned after the sorting.
4843 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4844 * with the reflection objects that represent them. Once all the tables are set up, the
4845 * reflection objects will contains the correct table index. fixup_method() will fixup the
4846 * tokens for the method with ILGenerator @ilgen.
4849 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4851 guint32 code_idx = GPOINTER_TO_UINT (value);
4852 MonoReflectionILTokenInfo *iltoken;
4853 MonoReflectionFieldBuilder *field;
4854 MonoReflectionCtorBuilder *ctor;
4855 MonoReflectionMethodBuilder *method;
4856 MonoReflectionTypeBuilder *tb;
4857 MonoReflectionArrayMethod *am;
4859 unsigned char *target;
4861 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4862 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4863 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4864 switch (target [3]) {
4865 case MONO_TABLE_FIELD:
4866 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4867 field = (MonoReflectionFieldBuilder *)iltoken->member;
4868 idx = field->table_idx;
4869 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4870 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4871 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4873 g_assert_not_reached ();
4876 case MONO_TABLE_METHOD:
4877 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4878 method = (MonoReflectionMethodBuilder *)iltoken->member;
4879 idx = method->table_idx;
4880 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4881 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4882 idx = ctor->table_idx;
4883 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4884 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4885 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4886 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4888 g_assert_not_reached ();
4891 case MONO_TABLE_TYPEDEF:
4892 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4893 g_assert_not_reached ();
4894 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4895 idx = tb->table_idx;
4897 case MONO_TABLE_MEMBERREF:
4898 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4899 am = (MonoReflectionArrayMethod*)iltoken->member;
4900 idx = am->table_idx;
4901 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4902 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4903 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4904 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4905 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4906 g_assert (m->klass->generic_class || m->klass->generic_container);
4908 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4910 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4911 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4912 g_assert (is_field_on_inst (f));
4914 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4915 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4917 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4919 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4921 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4924 g_assert_not_reached ();
4927 case MONO_TABLE_METHODSPEC:
4928 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4929 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4930 g_assert (mono_method_signature (m)->generic_param_count);
4932 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4934 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4937 g_assert_not_reached ();
4941 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4943 target [0] = idx & 0xff;
4944 target [1] = (idx >> 8) & 0xff;
4945 target [2] = (idx >> 16) & 0xff;
4952 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4953 * value is not known when the table is emitted.
4956 fixup_cattrs (MonoDynamicImage *assembly)
4958 MonoDynamicTable *table;
4960 guint32 type, i, idx, token;
4963 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4965 for (i = 0; i < table->rows; ++i) {
4966 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4968 type = values [MONO_CUSTOM_ATTR_TYPE];
4969 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4970 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4971 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4972 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4975 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4976 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4977 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4978 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4979 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4980 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4981 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4982 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4989 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
4991 MonoDynamicTable *table;
4994 mono_error_init (error);
4996 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4998 alloc_table (table, table->rows);
4999 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
5000 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
5001 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
5002 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
5003 return_val_if_nok (error, FALSE);
5004 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
5010 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
5012 MonoDynamicTable *table;
5016 char *b = blob_size;
5018 guint32 idx, offset;
5020 mono_error_init (error);
5022 if (rsrc->filename) {
5023 name = mono_string_to_utf8_checked (rsrc->filename, error);
5024 return_val_if_nok (error, FALSE);
5025 sname = g_path_get_basename (name);
5027 table = &assembly->tables [MONO_TABLE_FILE];
5029 alloc_table (table, table->rows);
5030 values = table->values + table->next_idx * MONO_FILE_SIZE;
5031 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5032 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5035 mono_sha1_get_digest_from_file (name, hash);
5036 mono_metadata_encode_value (20, b, &b);
5037 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5038 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5040 idx = table->next_idx++;
5042 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5048 data = mono_array_addr (rsrc->data, char, 0);
5049 len = mono_array_length (rsrc->data);
5055 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5056 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5057 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5058 mono_image_add_stream_data (&assembly->resources, data, len);
5062 * The entry should be emitted into the MANIFESTRESOURCE table of
5063 * the main module, but that needs to reference the FILE table
5064 * which isn't emitted yet.
5071 return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
5075 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
5077 gchar *ver, *p, *str;
5080 mono_error_init (error);
5082 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5083 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5084 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5085 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5088 ver = str = mono_string_to_utf8_checked (version, error);
5089 return_val_if_nok (error, FALSE);
5090 for (i = 0; i < 4; ++i) {
5091 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5097 /* handle Revision and Build */
5108 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5112 char *b = blob_size;
5117 len = mono_array_length (pkey);
5118 mono_metadata_encode_value (len, b, &b);
5119 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5120 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5122 assembly->public_key = (guint8 *)g_malloc (len);
5123 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5124 assembly->public_key_len = len;
5126 /* Special case: check for ECMA key (16 bytes) */
5127 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5128 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5129 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5130 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5131 /* minimum key size (in 2.0) is 384 bits */
5132 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5134 /* FIXME - verifier */
5135 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5136 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5138 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5144 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5146 MonoDynamicTable *table;
5147 MonoDynamicImage *assembly;
5148 MonoReflectionAssemblyBuilder *assemblyb;
5152 guint32 module_index;
5154 mono_error_init (error);
5156 assemblyb = moduleb->assemblyb;
5157 assembly = moduleb->dynamic_image;
5158 domain = mono_object_domain (assemblyb);
5160 /* Emit ASSEMBLY table */
5161 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5162 alloc_table (table, 1);
5163 values = table->values + MONO_ASSEMBLY_SIZE;
5164 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5165 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
5166 return_val_if_nok (error, FALSE);
5167 if (assemblyb->culture) {
5168 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
5169 return_val_if_nok (error, FALSE);
5171 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5173 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5174 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5175 if (!set_version_from_string (assemblyb->version, values, error))
5178 /* Emit FILE + EXPORTED_TYPE table */
5180 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5182 MonoReflectionModuleBuilder *file_module =
5183 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5184 if (file_module != moduleb) {
5185 if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
5188 if (file_module->types) {
5189 for (j = 0; j < file_module->num_types; ++j) {
5190 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5191 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5192 return_val_if_nok (error, FALSE);
5197 if (assemblyb->loaded_modules) {
5198 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5199 MonoReflectionModule *file_module =
5200 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5201 if (!mono_image_fill_file_table (domain, file_module, assembly, error))
5204 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5207 if (assemblyb->type_forwarders)
5208 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5210 /* Emit MANIFESTRESOURCE table */
5212 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5214 MonoReflectionModuleBuilder *file_module =
5215 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5216 /* The table for the main module is emitted later */
5217 if (file_module != moduleb) {
5219 if (file_module->resources) {
5220 int len = mono_array_length (file_module->resources);
5221 for (j = 0; j < len; ++j) {
5222 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5223 if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
5232 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5235 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5236 * for the modulebuilder @moduleb.
5237 * At the end of the process, method and field tokens are fixed up and the
5238 * on-disk compressed metadata representation is created.
5239 * Return TRUE on success, or FALSE on failure and sets @error
5242 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5244 MonoDynamicTable *table;
5245 MonoDynamicImage *assembly;
5246 MonoReflectionAssemblyBuilder *assemblyb;
5252 mono_error_init (error);
5254 assemblyb = moduleb->assemblyb;
5255 assembly = moduleb->dynamic_image;
5256 domain = mono_object_domain (assemblyb);
5258 if (assembly->text_rva)
5261 assembly->text_rva = START_TEXT_RVA;
5263 if (moduleb->is_main) {
5264 mono_image_emit_manifest (moduleb, error);
5265 return_val_if_nok (error, FALSE);
5268 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5269 table->rows = 1; /* .<Module> */
5271 alloc_table (table, table->rows);
5273 * Set the first entry.
5275 values = table->values + table->columns;
5276 values [MONO_TYPEDEF_FLAGS] = 0;
5277 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5278 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5279 values [MONO_TYPEDEF_EXTENDS] = 0;
5280 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5281 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5284 * handle global methods
5285 * FIXME: test what to do when global methods are defined in multiple modules.
5287 if (moduleb->global_methods) {
5288 table = &assembly->tables [MONO_TABLE_METHOD];
5289 table->rows += mono_array_length (moduleb->global_methods);
5290 alloc_table (table, table->rows);
5291 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5292 if (!mono_image_get_method_info (
5293 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5297 if (moduleb->global_fields) {
5298 table = &assembly->tables [MONO_TABLE_FIELD];
5299 table->rows += mono_array_length (moduleb->global_fields);
5300 alloc_table (table, table->rows);
5301 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5302 mono_image_get_field_info (
5303 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5310 table = &assembly->tables [MONO_TABLE_MODULE];
5311 alloc_table (table, 1);
5312 mono_image_fill_module_table (domain, moduleb, assembly, error);
5316 /* Collect all types into a list sorted by their table_idx */
5317 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5320 for (i = 0; i < moduleb->num_types; ++i) {
5321 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5322 collect_types (&types, type);
5325 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5326 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5327 table->rows += mono_ptr_array_size (types);
5328 alloc_table (table, table->rows);
5331 * Emit type names + namespaces at one place inside the string heap,
5332 * so load_class_names () needs to touch fewer pages.
5334 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5335 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5336 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
5340 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5341 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5342 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
5347 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5348 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5349 if (!mono_image_get_type_info (domain, type, assembly, error))
5354 * table->rows is already set above and in mono_image_fill_module_table.
5356 /* add all the custom attributes at the end, once all the indexes are stable */
5357 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5360 /* CAS assembly permissions */
5361 if (assemblyb->permissions_minimum)
5362 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5363 if (assemblyb->permissions_optional)
5364 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5365 if (assemblyb->permissions_refused)
5366 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5368 if (!module_add_cattrs (assembly, moduleb, error))
5372 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5374 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5375 * the final tokens and don't need another fixup pass. */
5377 if (moduleb->global_methods) {
5378 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5379 MonoReflectionMethodBuilder *mb = mono_array_get (
5380 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5381 if (!mono_image_add_methodimpl (assembly, mb, error))
5386 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5387 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5388 if (type->methods) {
5389 for (j = 0; j < type->num_methods; ++j) {
5390 MonoReflectionMethodBuilder *mb = mono_array_get (
5391 type->methods, MonoReflectionMethodBuilder*, j);
5393 if (!mono_image_add_methodimpl (assembly, mb, error))
5399 fixup_cattrs (assembly);
5402 mono_ptr_array_destroy (types);
5405 return mono_error_ok (error);
5408 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5411 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5413 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5416 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5420 guint32 import_lookup_table;
5424 guint32 import_address_table_rva;
5432 #ifndef DISABLE_REFLECTION_EMIT
5435 * mono_image_insert_string:
5436 * @module: module builder object
5439 * Insert @str into the user string stream of @module.
5442 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5444 MonoDynamicImage *assembly;
5449 if (!module->dynamic_image)
5450 mono_image_module_basic_init (module);
5452 assembly = module->dynamic_image;
5454 if (assembly->save) {
5455 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5456 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5457 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5459 char *swapped = g_malloc (2 * mono_string_length (str));
5460 const char *p = (const char*)mono_string_chars (str);
5462 swap_with_size (swapped, p, 2, mono_string_length (str));
5463 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5467 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5469 mono_image_add_stream_data (&assembly->us, "", 1);
5471 idx = assembly->us.index ++;
5474 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5476 return MONO_TOKEN_STRING | idx;
5480 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5484 MonoMethodSignature *sig;
5486 mono_error_init (error);
5488 klass = obj->vtable->klass;
5489 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5490 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5491 MonoMethodSignature *old;
5492 guint32 sig_token, parent;
5495 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5497 nargs = mono_array_length (opt_param_types);
5498 old = mono_method_signature (method);
5499 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5501 sig->hasthis = old->hasthis;
5502 sig->explicit_this = old->explicit_this;
5503 sig->call_convention = old->call_convention;
5504 sig->generic_param_count = old->generic_param_count;
5505 sig->param_count = old->param_count + nargs;
5506 sig->sentinelpos = old->param_count;
5507 sig->ret = old->ret;
5509 for (i = 0; i < old->param_count; i++)
5510 sig->params [i] = old->params [i];
5512 for (i = 0; i < nargs; i++) {
5513 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5514 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5515 if (!is_ok (error)) goto fail;
5518 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5519 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5520 parent >>= MONO_TYPEDEFORREF_BITS;
5522 parent <<= MONO_MEMBERREF_PARENT_BITS;
5523 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5525 sig_token = method_encode_signature (assembly, sig);
5526 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5527 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5528 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5529 ReflectionMethodBuilder rmb;
5530 guint32 parent, sig_token;
5531 int nopt_args, nparams, ngparams, i;
5533 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5536 rmb.opt_types = opt_param_types;
5537 nopt_args = mono_array_length (opt_param_types);
5539 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5540 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5541 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5543 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5544 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5545 sig->call_convention = rmb.call_conv;
5546 sig->generic_param_count = ngparams;
5547 sig->param_count = nparams + nopt_args;
5548 sig->sentinelpos = nparams;
5549 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5550 if (!is_ok (error)) goto fail;
5552 for (i = 0; i < nparams; i++) {
5553 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5554 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5555 if (!is_ok (error)) goto fail;
5558 for (i = 0; i < nopt_args; i++) {
5559 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5560 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5561 if (!is_ok (error)) goto fail;
5564 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5568 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5569 if (!mono_error_ok (error))
5571 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5573 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5574 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5576 char *name = mono_string_to_utf8_checked (rmb.name, error);
5577 if (!is_ok (error)) goto fail;
5578 token = mono_image_get_varargs_method_token (
5579 assembly, parent, name, sig_token);
5582 g_error ("requested method token for %s\n", klass->name);
5585 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5586 register_dyn_token (assembly, token, obj);
5589 g_assert (!mono_error_ok (error));
5594 * mono_image_create_token:
5595 * @assembly: a dynamic assembly
5597 * @register_token: Whenever to register the token in the assembly->tokens hash.
5599 * Get a token to insert in the IL code stream for the given MemberInfo.
5600 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5601 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5605 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5606 gboolean create_open_instance, gboolean register_token,
5612 mono_error_init (error);
5614 klass = obj->vtable->klass;
5616 /* Check for user defined reflection objects */
5617 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5618 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5619 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5623 if (strcmp (klass->name, "MethodBuilder") == 0) {
5624 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5625 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5627 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5628 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5630 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5631 if (!mono_error_ok (error))
5634 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5635 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5636 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5637 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5639 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5640 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5642 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5643 if (!mono_error_ok (error))
5646 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5647 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5648 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5649 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5650 if (tb->generic_params) {
5651 token = mono_image_get_generic_field_token (assembly, fb, error);
5652 return_val_if_nok (error, 0);
5654 if (tb->module->dynamic_image == assembly) {
5655 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5657 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5660 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5661 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5662 if (create_open_instance && tb->generic_params) {
5664 init_type_builder_generics (obj, error);
5665 return_val_if_nok (error, 0);
5666 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5667 return_val_if_nok (error, 0);
5668 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5669 token = mono_metadata_token_from_dor (token);
5670 } else if (tb->module->dynamic_image == assembly) {
5671 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5674 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5675 return_val_if_nok (error, 0);
5676 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5678 } else if (strcmp (klass->name, "RuntimeType") == 0) {
5679 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5680 return_val_if_nok (error, 0);
5681 MonoClass *mc = mono_class_from_mono_type (type);
5682 token = mono_metadata_token_from_dor (
5683 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5684 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5685 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5686 return_val_if_nok (error, 0);
5687 token = mono_metadata_token_from_dor (
5688 mono_image_typedef_or_ref (assembly, type));
5689 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5690 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5691 return_val_if_nok (error, 0);
5692 token = mono_metadata_token_from_dor (
5693 mono_image_typedef_or_ref (assembly, type));
5694 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5695 strcmp (klass->name, "MonoMethod") == 0 ||
5696 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5697 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5698 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5699 if (m->method->is_inflated) {
5700 if (create_open_instance)
5701 token = mono_image_get_methodspec_token (assembly, m->method);
5703 token = mono_image_get_inflated_method_token (assembly, m->method);
5704 } else if ((m->method->klass->image == &assembly->image) &&
5705 !m->method->klass->generic_class) {
5706 static guint32 method_table_idx = 0xffffff;
5707 if (m->method->klass->wastypebuilder) {
5708 /* we use the same token as the one that was assigned
5709 * to the Methodbuilder.
5710 * FIXME: do the equivalent for Fields.
5712 token = m->method->token;
5715 * Each token should have a unique index, but the indexes are
5716 * assigned by managed code, so we don't know about them. An
5717 * easy solution is to count backwards...
5719 method_table_idx --;
5720 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5723 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5725 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5726 } else if (strcmp (klass->name, "MonoField") == 0) {
5727 MonoReflectionField *f = (MonoReflectionField *)obj;
5728 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5729 static guint32 field_table_idx = 0xffffff;
5731 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5733 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5735 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5736 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5737 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5738 token = mono_image_get_array_token (assembly, m, error);
5739 return_val_if_nok (error, 0);
5740 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5741 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5742 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5743 return_val_if_nok (error, 0);
5744 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5745 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5746 return_val_if_nok (error, 0);
5747 token = mono_metadata_token_from_dor (
5748 mono_image_typedef_or_ref (assembly, type));
5749 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5750 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5751 token = mono_image_get_field_on_inst_token (assembly, f, error);
5752 return_val_if_nok (error, 0);
5753 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5754 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5755 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5756 if (!mono_error_ok (error))
5758 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5759 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5760 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5761 if (!mono_error_ok (error))
5763 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5764 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5765 return_val_if_nok (error, 0);
5766 token = mono_metadata_token_from_dor (
5767 mono_image_typedef_or_ref (assembly, type));
5769 g_error ("requested token for %s\n", klass->name);
5773 mono_image_register_token (assembly, token, obj);
5779 * mono_image_register_token:
5781 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5782 * the Module.ResolveXXXToken () methods to work.
5785 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5789 dynamic_image_lock (assembly);
5790 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5792 /* There could be multiple MethodInfo objects with the same token */
5793 //g_assert (prev == obj);
5795 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5797 dynamic_image_unlock (assembly);
5800 static MonoDynamicImage*
5801 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5803 static const guchar entrycode [16] = {0xff, 0x25, 0};
5804 MonoDynamicImage *image;
5807 const char *version;
5809 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5810 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5812 version = mono_get_runtime_info ()->runtime_version;
5815 /* The MonoGHashTable's need GC tracking */
5816 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5818 image = g_new0 (MonoDynamicImage, 1);
5821 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5823 /*g_print ("created image %p\n", image);*/
5824 /* keep in sync with image.c */
5825 image->image.name = assembly_name;
5826 image->image.assembly_name = image->image.name; /* they may be different */
5827 image->image.module_name = module_name;
5828 image->image.version = g_strdup (version);
5829 image->image.md_version_major = 1;
5830 image->image.md_version_minor = 1;
5831 image->image.dynamic = TRUE;
5833 image->image.references = g_new0 (MonoAssembly*, 1);
5834 image->image.references [0] = NULL;
5836 mono_image_init (&image->image);
5838 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");
5839 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5840 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5841 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5842 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5843 image->handleref = g_hash_table_new (NULL, NULL);
5844 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");
5845 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5846 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");
5847 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");
5848 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5849 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5850 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5851 image->gen_params = g_ptr_array_new ();
5852 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5854 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5855 string_heap_init (&image->sheap);
5856 mono_image_add_stream_data (&image->us, "", 1);
5857 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5858 /* import tables... */
5859 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5860 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5861 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5862 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5863 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5864 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5865 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5866 stream_data_align (&image->code);
5868 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5870 for (i=0; i < MONO_TABLE_NUM; ++i) {
5871 image->tables [i].next_idx = 1;
5872 image->tables [i].columns = table_sizes [i];
5875 image->image.assembly = (MonoAssembly*)assembly;
5876 image->run = assembly->run;
5877 image->save = assembly->save;
5878 image->pe_kind = 0x1; /* ILOnly */
5879 image->machine = 0x14c; /* I386 */
5881 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5883 dynamic_images_lock ();
5885 if (!dynamic_images)
5886 dynamic_images = g_ptr_array_new ();
5888 g_ptr_array_add (dynamic_images, image);
5890 dynamic_images_unlock ();
5897 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5903 release_hashtable (MonoGHashTable **hash)
5906 mono_g_hash_table_destroy (*hash);
5912 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5914 release_hashtable (&image->token_fixups);
5915 release_hashtable (&image->handleref_managed);
5916 release_hashtable (&image->tokens);
5917 release_hashtable (&image->remapped_tokens);
5918 release_hashtable (&image->generic_def_objects);
5919 release_hashtable (&image->methodspec);
5922 // Free dynamic image pass one: Free resources but not image itself
5924 mono_dynamic_image_free (MonoDynamicImage *image)
5926 MonoDynamicImage *di = image;
5931 mono_g_hash_table_destroy (di->methodspec);
5933 g_hash_table_destroy (di->typespec);
5935 g_hash_table_destroy (di->typeref);
5937 g_hash_table_destroy (di->handleref);
5938 if (di->handleref_managed)
5939 mono_g_hash_table_destroy (di->handleref_managed);
5941 mono_g_hash_table_destroy (di->tokens);
5942 if (di->remapped_tokens)
5943 mono_g_hash_table_destroy (di->remapped_tokens);
5944 if (di->generic_def_objects)
5945 mono_g_hash_table_destroy (di->generic_def_objects);
5946 if (di->blob_cache) {
5947 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5948 g_hash_table_destroy (di->blob_cache);
5950 if (di->standalonesig_cache)
5951 g_hash_table_destroy (di->standalonesig_cache);
5952 for (list = di->array_methods; list; list = list->next) {
5953 ArrayMethod *am = (ArrayMethod *)list->data;
5958 g_list_free (di->array_methods);
5959 if (di->gen_params) {
5960 for (i = 0; i < di->gen_params->len; i++) {
5961 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5962 mono_gc_deregister_root ((char*) &entry->gparam);
5965 g_ptr_array_free (di->gen_params, TRUE);
5967 if (di->token_fixups)
5968 mono_g_hash_table_destroy (di->token_fixups);
5969 if (di->method_to_table_idx)
5970 g_hash_table_destroy (di->method_to_table_idx);
5971 if (di->field_to_table_idx)
5972 g_hash_table_destroy (di->field_to_table_idx);
5973 if (di->method_aux_hash)
5974 g_hash_table_destroy (di->method_aux_hash);
5975 if (di->vararg_aux_hash)
5976 g_hash_table_destroy (di->vararg_aux_hash);
5977 g_free (di->strong_name);
5978 g_free (di->win32_res);
5980 g_free (di->public_key);
5982 /*g_print ("string heap destroy for image %p\n", di);*/
5983 mono_dynamic_stream_reset (&di->sheap);
5984 mono_dynamic_stream_reset (&di->code);
5985 mono_dynamic_stream_reset (&di->resources);
5986 mono_dynamic_stream_reset (&di->us);
5987 mono_dynamic_stream_reset (&di->blob);
5988 mono_dynamic_stream_reset (&di->tstream);
5989 mono_dynamic_stream_reset (&di->guid);
5990 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5991 g_free (di->tables [i].values);
5994 dynamic_images_lock ();
5997 g_ptr_array_remove (dynamic_images, di);
5999 dynamic_images_unlock ();
6002 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
6004 mono_dynamic_image_free_image (MonoDynamicImage *image)
6006 /* See create_dynamic_mono_image () */
6008 /* Allocated using GC_MALLOC */
6014 #ifndef DISABLE_REFLECTION_EMIT
6017 * mono_image_basic_init:
6018 * @assembly: an assembly builder object
6020 * Create the MonoImage that represents the assembly builder and setup some
6021 * of the helper hash table and the basic metadata streams.
6024 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
6027 MonoDynamicAssembly *assembly;
6028 MonoDynamicImage *image;
6029 MonoDomain *domain = mono_object_domain (assemblyb);
6031 if (assemblyb->dynamic_assembly)
6035 /* assembly->assembly.image might be GC allocated */
6036 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6038 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6041 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6043 assembly->assembly.ref_count = 1;
6044 assembly->assembly.dynamic = TRUE;
6045 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6046 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6047 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6048 if (mono_error_set_pending_exception (&error))
6050 if (assemblyb->culture) {
6051 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6052 if (mono_error_set_pending_exception (&error))
6055 assembly->assembly.aname.culture = g_strdup ("");
6057 if (assemblyb->version) {
6058 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6059 if (mono_error_set_pending_exception (&error))
6061 char **version = g_strsplit (vstr, ".", 4);
6062 char **parts = version;
6063 assembly->assembly.aname.major = atoi (*parts++);
6064 assembly->assembly.aname.minor = atoi (*parts++);
6065 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6066 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6068 g_strfreev (version);
6071 assembly->assembly.aname.major = 0;
6072 assembly->assembly.aname.minor = 0;
6073 assembly->assembly.aname.build = 0;
6074 assembly->assembly.aname.revision = 0;
6077 assembly->run = assemblyb->access != 2;
6078 assembly->save = assemblyb->access != 1;
6079 assembly->domain = domain;
6081 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6082 if (mono_error_set_pending_exception (&error))
6084 image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6085 image->initial_image = TRUE;
6086 assembly->assembly.aname.name = image->image.name;
6087 assembly->assembly.image = &image->image;
6088 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6089 /* -1 to correct for the trailing NULL byte */
6090 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6091 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6093 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6096 mono_domain_assemblies_lock (domain);
6097 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6098 mono_domain_assemblies_unlock (domain);
6100 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6102 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6104 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6107 #endif /* !DISABLE_REFLECTION_EMIT */
6109 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6112 calc_section_size (MonoDynamicImage *assembly)
6116 /* alignment constraints */
6117 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6118 g_assert ((assembly->code.index % 4) == 0);
6119 assembly->meta_size += 3;
6120 assembly->meta_size &= ~3;
6121 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6122 g_assert ((assembly->resources.index % 4) == 0);
6124 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6125 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6128 if (assembly->win32_res) {
6129 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6131 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6132 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6136 assembly->sections [MONO_SECTION_RELOC].size = 12;
6137 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6147 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6151 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6153 ResTreeNode *t1 = (ResTreeNode*)a;
6154 ResTreeNode *t2 = (ResTreeNode*)b;
6156 return t1->id - t2->id;
6160 * resource_tree_create:
6162 * Organize the resources into a resource tree.
6164 static ResTreeNode *
6165 resource_tree_create (MonoArray *win32_resources)
6167 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6171 tree = g_new0 (ResTreeNode, 1);
6173 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6174 MonoReflectionWin32Resource *win32_res =
6175 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6179 /* FIXME: BUG: this stores managed references in unmanaged memory */
6180 lang_node = g_new0 (ResTreeNode, 1);
6181 lang_node->id = win32_res->lang_id;
6182 lang_node->win32_res = win32_res;
6184 /* Create type node if neccesary */
6186 for (l = tree->children; l; l = l->next)
6187 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6188 type_node = (ResTreeNode*)l->data;
6193 type_node = g_new0 (ResTreeNode, 1);
6194 type_node->id = win32_res->res_type;
6197 * The resource types have to be sorted otherwise
6198 * Windows Explorer can't display the version information.
6200 tree->children = g_slist_insert_sorted (tree->children,
6201 type_node, resource_tree_compare_by_id);
6204 /* Create res node if neccesary */
6206 for (l = type_node->children; l; l = l->next)
6207 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6208 res_node = (ResTreeNode*)l->data;
6213 res_node = g_new0 (ResTreeNode, 1);
6214 res_node->id = win32_res->res_id;
6215 type_node->children = g_slist_append (type_node->children, res_node);
6218 res_node->children = g_slist_append (res_node->children, lang_node);
6225 * resource_tree_encode:
6227 * Encode the resource tree into the format used in the PE file.
6230 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6233 MonoPEResourceDir dir;
6234 MonoPEResourceDirEntry dir_entry;
6235 MonoPEResourceDataEntry data_entry;
6237 guint32 res_id_entries;
6240 * For the format of the resource directory, see the article
6241 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6245 memset (&dir, 0, sizeof (dir));
6246 memset (&dir_entry, 0, sizeof (dir_entry));
6247 memset (&data_entry, 0, sizeof (data_entry));
6249 g_assert (sizeof (dir) == 16);
6250 g_assert (sizeof (dir_entry) == 8);
6251 g_assert (sizeof (data_entry) == 16);
6253 node->offset = p - begin;
6255 /* IMAGE_RESOURCE_DIRECTORY */
6256 res_id_entries = g_slist_length (node->children);
6257 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6259 memcpy (p, &dir, sizeof (dir));
6262 /* Reserve space for entries */
6264 p += sizeof (dir_entry) * res_id_entries;
6266 /* Write children */
6267 for (l = node->children; l; l = l->next) {
6268 ResTreeNode *child = (ResTreeNode*)l->data;
6270 if (child->win32_res) {
6273 child->offset = p - begin;
6275 /* IMAGE_RESOURCE_DATA_ENTRY */
6276 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6277 size = mono_array_length (child->win32_res->res_data);
6278 data_entry.rde_size = GUINT32_TO_LE (size);
6280 memcpy (p, &data_entry, sizeof (data_entry));
6281 p += sizeof (data_entry);
6283 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6286 resource_tree_encode (child, begin, p, &p);
6290 /* IMAGE_RESOURCE_ENTRY */
6291 for (l = node->children; l; l = l->next) {
6292 ResTreeNode *child = (ResTreeNode*)l->data;
6294 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6295 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6297 memcpy (entries, &dir_entry, sizeof (dir_entry));
6298 entries += sizeof (dir_entry);
6305 resource_tree_free (ResTreeNode * node)
6308 for (list = node->children; list; list = list->next)
6309 resource_tree_free ((ResTreeNode*)list->data);
6310 g_slist_free(node->children);
6315 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6320 MonoReflectionWin32Resource *win32_res;
6323 if (!assemblyb->win32_resources)
6327 * Resources are stored in a three level tree inside the PE file.
6328 * - level one contains a node for each type of resource
6329 * - level two contains a node for each resource
6330 * - level three contains a node for each instance of a resource for a
6331 * specific language.
6334 tree = resource_tree_create (assemblyb->win32_resources);
6336 /* Estimate the size of the encoded tree */
6338 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6339 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6340 size += mono_array_length (win32_res->res_data);
6342 /* Directory structure */
6343 size += mono_array_length (assemblyb->win32_resources) * 256;
6344 p = buf = (char *)g_malloc (size);
6346 resource_tree_encode (tree, p, p, &p);
6348 g_assert (p - buf <= size);
6350 assembly->win32_res = (char *)g_malloc (p - buf);
6351 assembly->win32_res_size = p - buf;
6352 memcpy (assembly->win32_res, buf, p - buf);
6355 resource_tree_free (tree);
6359 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6361 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6364 p += sizeof (MonoPEResourceDir);
6365 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6366 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6367 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6368 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6369 fixup_resource_directory (res_section, child, rva);
6371 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6372 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6375 p += sizeof (MonoPEResourceDirEntry);
6380 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6383 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6384 g_error ("WriteFile returned %d\n", GetLastError ());
6388 * mono_image_create_pefile:
6389 * @mb: a module builder object
6391 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6392 * assembly->pefile where it can be easily retrieved later in chunks.
6395 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6397 MonoMSDOSHeader *msdos;
6398 MonoDotNetHeader *header;
6399 MonoSectionTable *section;
6400 MonoCLIHeader *cli_header;
6401 guint32 size, image_size, virtual_base, text_offset;
6402 guint32 header_start, section_start, file_offset, virtual_offset;
6403 MonoDynamicImage *assembly;
6404 MonoReflectionAssemblyBuilder *assemblyb;
6405 MonoDynamicStream pefile_stream = {0};
6406 MonoDynamicStream *pefile = &pefile_stream;
6408 guint32 *rva, value;
6410 static const unsigned char msheader[] = {
6411 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6412 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6415 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6416 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6417 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6418 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6421 mono_error_init (error);
6423 assemblyb = mb->assemblyb;
6425 mono_image_basic_init (assemblyb);
6426 assembly = mb->dynamic_image;
6428 assembly->pe_kind = assemblyb->pe_kind;
6429 assembly->machine = assemblyb->machine;
6430 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6431 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6433 if (!mono_image_build_metadata (mb, error))
6437 if (mb->is_main && assemblyb->resources) {
6438 int len = mono_array_length (assemblyb->resources);
6439 for (i = 0; i < len; ++i) {
6440 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
6445 if (mb->resources) {
6446 int len = mono_array_length (mb->resources);
6447 for (i = 0; i < len; ++i) {
6448 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
6453 if (!build_compressed_metadata (assembly, error))
6457 assembly_add_win32_resources (assembly, assemblyb);
6459 nsections = calc_section_size (assembly);
6461 /* The DOS header and stub */
6462 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6463 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6465 /* the dotnet header */
6466 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6468 /* the section tables */
6469 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6471 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6472 virtual_offset = VIRT_ALIGN;
6475 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6476 if (!assembly->sections [i].size)
6479 file_offset += FILE_ALIGN - 1;
6480 file_offset &= ~(FILE_ALIGN - 1);
6481 virtual_offset += VIRT_ALIGN - 1;
6482 virtual_offset &= ~(VIRT_ALIGN - 1);
6484 assembly->sections [i].offset = file_offset;
6485 assembly->sections [i].rva = virtual_offset;
6487 file_offset += assembly->sections [i].size;
6488 virtual_offset += assembly->sections [i].size;
6489 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6492 file_offset += FILE_ALIGN - 1;
6493 file_offset &= ~(FILE_ALIGN - 1);
6495 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6497 /* back-patch info */
6498 msdos = (MonoMSDOSHeader*)pefile->data;
6499 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6501 header = (MonoDotNetHeader*)(pefile->data + header_start);
6502 header->pesig [0] = 'P';
6503 header->pesig [1] = 'E';
6505 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6506 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6507 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6508 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6509 if (assemblyb->pekind == 1) {
6511 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6514 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6517 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6519 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6520 header->pe.pe_major = 6;
6521 header->pe.pe_minor = 0;
6522 size = assembly->sections [MONO_SECTION_TEXT].size;
6523 size += FILE_ALIGN - 1;
6524 size &= ~(FILE_ALIGN - 1);
6525 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6526 size = assembly->sections [MONO_SECTION_RSRC].size;
6527 size += FILE_ALIGN - 1;
6528 size &= ~(FILE_ALIGN - 1);
6529 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6530 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6531 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6532 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6533 /* pe_rva_entry_point always at the beginning of the text section */
6534 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6536 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6537 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6538 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6539 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6540 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6541 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6542 size = section_start;
6543 size += FILE_ALIGN - 1;
6544 size &= ~(FILE_ALIGN - 1);
6545 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6547 size += VIRT_ALIGN - 1;
6548 size &= ~(VIRT_ALIGN - 1);
6549 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6552 // Translate the PEFileKind value to the value expected by the Windows loader
6558 // PEFileKinds.Dll == 1
6559 // PEFileKinds.ConsoleApplication == 2
6560 // PEFileKinds.WindowApplication == 3
6563 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6564 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6566 if (assemblyb->pekind == 3)
6571 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6573 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6574 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6575 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6576 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6577 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6578 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6580 /* fill data directory entries */
6582 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6583 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6585 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6586 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6588 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6589 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6590 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6591 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6592 /* patch entrypoint name */
6593 if (assemblyb->pekind == 1)
6594 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6596 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6597 /* patch imported function RVA name */
6598 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6599 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6601 /* the import table */
6602 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6603 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6604 /* patch imported dll RVA name and other entries in the dir */
6605 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6606 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6607 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6608 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6609 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6610 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6612 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6613 value = (assembly->text_rva + assembly->imp_names_offset);
6614 *p++ = (value) & 0xff;
6615 *p++ = (value >> 8) & (0xff);
6616 *p++ = (value >> 16) & (0xff);
6617 *p++ = (value >> 24) & (0xff);
6619 /* the CLI header info */
6620 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6621 cli_header->ch_size = GUINT32_FROM_LE (72);
6622 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6623 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6624 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6625 if (assemblyb->entry_point) {
6626 guint32 table_idx = 0;
6627 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6628 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6629 table_idx = methodb->table_idx;
6631 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6633 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6635 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6637 /* The embedded managed resources */
6638 text_offset = assembly->text_rva + assembly->code.index;
6639 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6640 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6641 text_offset += assembly->resources.index;
6642 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6643 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6644 text_offset += assembly->meta_size;
6645 if (assembly->strong_name_size) {
6646 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6647 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6648 text_offset += assembly->strong_name_size;
6651 /* write the section tables and section content */
6652 section = (MonoSectionTable*)(pefile->data + section_start);
6653 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6654 static const char section_names [][7] = {
6655 ".text", ".rsrc", ".reloc"
6657 if (!assembly->sections [i].size)
6659 strcpy (section->st_name, section_names [i]);
6660 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6661 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6662 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6663 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6664 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6665 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6666 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6670 checked_write_file (file, pefile->data, pefile->index);
6672 mono_dynamic_stream_reset (pefile);
6674 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6675 if (!assembly->sections [i].size)
6678 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6679 g_error ("SetFilePointer returned %d\n", GetLastError ());
6682 case MONO_SECTION_TEXT:
6683 /* patch entry point */
6684 p = (guchar*)(assembly->code.data + 2);
6685 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6686 *p++ = (value) & 0xff;
6687 *p++ = (value >> 8) & 0xff;
6688 *p++ = (value >> 16) & 0xff;
6689 *p++ = (value >> 24) & 0xff;
6691 checked_write_file (file, assembly->code.data, assembly->code.index);
6692 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6693 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6694 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6697 g_free (assembly->image.raw_metadata);
6699 case MONO_SECTION_RELOC: {
6703 guint16 type_and_offset;
6707 g_assert (sizeof (reloc) == 12);
6709 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6710 reloc.block_size = GUINT32_FROM_LE (12);
6713 * the entrypoint is always at the start of the text section
6714 * 3 is IMAGE_REL_BASED_HIGHLOW
6715 * 2 is patch_size_rva - text_rva
6717 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6720 checked_write_file (file, &reloc, sizeof (reloc));
6724 case MONO_SECTION_RSRC:
6725 if (assembly->win32_res) {
6727 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6728 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6729 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6733 g_assert_not_reached ();
6737 /* check that the file is properly padded */
6738 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6739 g_error ("SetFilePointer returned %d\n", GetLastError ());
6740 if (! SetEndOfFile (file))
6741 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6743 mono_dynamic_stream_reset (&assembly->code);
6744 mono_dynamic_stream_reset (&assembly->us);
6745 mono_dynamic_stream_reset (&assembly->blob);
6746 mono_dynamic_stream_reset (&assembly->guid);
6747 mono_dynamic_stream_reset (&assembly->sheap);
6749 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6750 g_hash_table_destroy (assembly->blob_cache);
6751 assembly->blob_cache = NULL;
6756 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6759 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6761 g_assert_not_reached ();
6764 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6766 #ifndef DISABLE_REFLECTION_EMIT
6768 MonoReflectionModule *
6769 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6773 MonoImageOpenStatus status;
6774 MonoDynamicAssembly *assembly;
6775 guint32 module_count;
6776 MonoImage **new_modules;
6777 gboolean *new_modules_loaded;
6779 mono_error_init (error);
6781 name = mono_string_to_utf8_checked (fileName, error);
6782 return_val_if_nok (error, NULL);
6784 image = mono_image_open (name, &status);
6786 if (status == MONO_IMAGE_ERROR_ERRNO)
6787 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6789 mono_error_set_bad_image_name (error, name, NULL);
6796 assembly = ab->dynamic_assembly;
6797 image->assembly = (MonoAssembly*)assembly;
6799 module_count = image->assembly->image->module_count;
6800 new_modules = g_new0 (MonoImage *, module_count + 1);
6801 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6803 if (image->assembly->image->modules)
6804 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6805 if (image->assembly->image->modules_loaded)
6806 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6807 new_modules [module_count] = image;
6808 new_modules_loaded [module_count] = TRUE;
6809 mono_image_addref (image);
6811 g_free (image->assembly->image->modules);
6812 image->assembly->image->modules = new_modules;
6813 image->assembly->image->modules_loaded = new_modules_loaded;
6814 image->assembly->image->module_count ++;
6816 mono_assembly_load_references (image, &status);
6818 mono_image_close (image);
6819 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6823 return mono_module_get_object_checked (mono_domain_get (), image, error);
6826 #endif /* DISABLE_REFLECTION_EMIT */
6829 * We need to return always the same object for MethodInfo, FieldInfo etc..
6830 * but we need to consider the reflected type.
6831 * type uses a different hash, since it uses custom hash/equal functions.
6836 MonoClass *refclass;
6840 reflected_equal (gconstpointer a, gconstpointer b) {
6841 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6842 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6844 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6848 reflected_hash (gconstpointer a) {
6849 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6850 return mono_aligned_addr_hash (ea->item);
6853 #define CHECK_OBJECT(t,p,k) \
6859 mono_domain_lock (domain); \
6860 if (!domain->refobject_hash) \
6861 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"); \
6862 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6863 mono_domain_unlock (domain); \
6866 mono_domain_unlock (domain); \
6869 #ifdef HAVE_BOEHM_GC
6870 /* ReflectedEntry doesn't need to be GC tracked */
6871 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6872 #define FREE_REFENTRY(entry) g_free ((entry))
6873 #define REFENTRY_REQUIRES_CLEANUP
6875 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6877 #define FREE_REFENTRY(entry)
6880 #define CACHE_OBJECT(t,p,o,k) \
6883 ReflectedEntry pe; \
6885 pe.refclass = (k); \
6886 mono_domain_lock (domain); \
6887 if (!domain->refobject_hash) \
6888 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"); \
6889 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6891 ReflectedEntry *e = ALLOC_REFENTRY; \
6893 e->refclass = (k); \
6894 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6897 mono_domain_unlock (domain); \
6902 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6904 mono_domain_lock (domain);
6905 if (domain->refobject_hash) {
6907 gpointer orig_pe, orig_value;
6910 pe.refclass = klass;
6911 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6912 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6913 FREE_REFENTRY (orig_pe);
6916 mono_domain_unlock (domain);
6919 #ifdef REFENTRY_REQUIRES_CLEANUP
6921 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6923 FREE_REFENTRY (key);
6928 mono_reflection_cleanup_domain (MonoDomain *domain)
6930 if (domain->refobject_hash) {
6931 /*let's avoid scanning the whole hashtable if not needed*/
6932 #ifdef REFENTRY_REQUIRES_CLEANUP
6933 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6935 mono_g_hash_table_destroy (domain->refobject_hash);
6936 domain->refobject_hash = NULL;
6940 #ifndef DISABLE_REFLECTION_EMIT
6942 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6944 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6948 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6950 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6954 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6956 MonoDynamicImage *image = moduleb->dynamic_image;
6957 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6958 mono_error_init (error);
6961 MonoImage **new_modules;
6963 char *name, *fqname;
6965 * FIXME: we already created an image in mono_image_basic_init (), but
6966 * we don't know which module it belongs to, since that is only
6967 * determined at assembly save time.
6969 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6970 name = mono_string_to_utf8_checked (ab->name, error);
6971 return_val_if_nok (error, FALSE);
6972 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6973 if (!is_ok (error)) {
6977 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6979 moduleb->module.image = &image->image;
6980 moduleb->dynamic_image = image;
6981 register_module (mono_object_domain (moduleb), moduleb, image);
6983 /* register the module with the assembly */
6984 ass = ab->dynamic_assembly->assembly.image;
6985 module_count = ass->module_count;
6986 new_modules = g_new0 (MonoImage *, module_count + 1);
6989 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6990 new_modules [module_count] = &image->image;
6991 mono_image_addref (&image->image);
6993 g_free (ass->modules);
6994 ass->modules = new_modules;
6995 ass->module_count ++;
7001 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
7004 (void) image_module_basic_init (moduleb, &error);
7005 mono_error_set_pending_exception (&error);
7009 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
7011 MonoDynamicImage *image = moduleb->dynamic_image;
7013 g_assert (type->type);
7014 image->wrappers_type = mono_class_from_mono_type (type->type);
7020 * mono_assembly_get_object:
7021 * @domain: an app domain
7022 * @assembly: an assembly
7024 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7026 MonoReflectionAssembly*
7027 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
7030 MonoReflectionAssembly *result;
7031 result = mono_assembly_get_object_checked (domain, assembly, &error);
7032 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7036 * mono_assembly_get_object_checked:
7037 * @domain: an app domain
7038 * @assembly: an assembly
7040 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7042 MonoReflectionAssembly*
7043 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7045 MonoReflectionAssembly *res;
7047 mono_error_init (error);
7049 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7050 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7053 res->assembly = assembly;
7055 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7060 MonoReflectionModule*
7061 mono_module_get_object (MonoDomain *domain, MonoImage *image)
7064 MonoReflectionModule *result;
7065 result = mono_module_get_object_checked (domain, image, &error);
7066 mono_error_cleanup (&error);
7070 MonoReflectionModule*
7071 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7073 MonoReflectionModule *res;
7076 mono_error_init (error);
7077 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7078 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7083 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7086 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7088 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7089 basename = g_path_get_basename (image->name);
7090 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7091 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7095 if (image->assembly->image == image) {
7096 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7100 if (image->assembly->image->modules) {
7101 for (i = 0; i < image->assembly->image->module_count; i++) {
7102 if (image->assembly->image->modules [i] == image)
7103 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7105 g_assert (res->token);
7109 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7112 MonoReflectionModule*
7113 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7116 MonoReflectionModule *result;
7117 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7118 mono_error_cleanup (&error);
7122 MonoReflectionModule*
7123 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7125 MonoReflectionModule *res;
7126 MonoTableInfo *table;
7127 guint32 cols [MONO_FILE_SIZE];
7129 guint32 i, name_idx;
7132 mono_error_init (error);
7134 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7138 table = &image->tables [MONO_TABLE_FILE];
7139 g_assert (table_index < table->rows);
7140 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7143 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7146 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7147 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7149 /* Check whenever the row has a corresponding row in the moduleref table */
7150 table = &image->tables [MONO_TABLE_MODULEREF];
7151 for (i = 0; i < table->rows; ++i) {
7152 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7153 val = mono_metadata_string_heap (image, name_idx);
7154 if (strcmp (val, name) == 0)
7155 res->image = image->modules [i];
7158 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7159 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7160 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7161 res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
7162 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7168 verify_safe_for_managed_space (MonoType *type)
7170 switch (type->type) {
7172 case MONO_TYPE_ARRAY:
7173 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7175 return verify_safe_for_managed_space (type->data.type);
7176 case MONO_TYPE_SZARRAY:
7177 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7178 case MONO_TYPE_GENERICINST: {
7179 MonoGenericInst *inst = type->data.generic_class->inst;
7183 for (i = 0; i < inst->type_argc; ++i)
7184 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7190 case MONO_TYPE_MVAR:
7198 mono_type_normalize (MonoType *type)
7201 MonoGenericClass *gclass;
7202 MonoGenericInst *ginst;
7204 MonoGenericContainer *gcontainer;
7205 MonoType **argv = NULL;
7206 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7208 if (type->type != MONO_TYPE_GENERICINST)
7211 gclass = type->data.generic_class;
7212 ginst = gclass->context.class_inst;
7213 if (!ginst->is_open)
7216 gtd = gclass->container_class;
7217 gcontainer = gtd->generic_container;
7218 argv = g_newa (MonoType*, ginst->type_argc);
7220 for (i = 0; i < ginst->type_argc; ++i) {
7221 MonoType *t = ginst->type_argv [i], *norm;
7222 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7223 is_denorm_gtd = FALSE;
7224 norm = mono_type_normalize (t);
7227 requires_rebind = TRUE;
7231 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7233 if (requires_rebind) {
7234 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7235 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7241 * mono_type_get_object:
7242 * @domain: an app domain
7245 * Return an System.MonoType object representing the type @type.
7248 mono_type_get_object (MonoDomain *domain, MonoType *type)
7251 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7252 mono_error_cleanup (&error);
7258 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7260 MonoType *norm_type;
7261 MonoReflectionType *res;
7264 mono_error_init (error);
7266 klass = mono_class_from_mono_type (type);
7268 /*we must avoid using @type as it might have come
7269 * from a mono_metadata_type_dup and the caller
7270 * expects that is can be freed.
7271 * Using the right type from
7273 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7275 /* void is very common */
7276 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7277 return (MonoReflectionType*)domain->typeof_void;
7280 * If the vtable of the given class was already created, we can use
7281 * the MonoType from there and avoid all locking and hash table lookups.
7283 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7284 * that the resulting object is different.
7286 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7287 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7288 if (vtable && vtable->type)
7289 return (MonoReflectionType *)vtable->type;
7292 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7293 mono_domain_lock (domain);
7294 if (!domain->type_hash)
7295 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7296 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7297 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7298 mono_domain_unlock (domain);
7299 mono_loader_unlock ();
7303 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7304 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7305 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7306 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7307 * artifact of how generics are encoded and should be transparent to managed code so we
7308 * need to weed out this diference when retrieving managed System.Type objects.
7310 norm_type = mono_type_normalize (type);
7311 if (norm_type != type) {
7312 res = mono_type_get_object_checked (domain, norm_type, error);
7313 if (!mono_error_ok (error))
7315 mono_g_hash_table_insert (domain->type_hash, type, res);
7316 mono_domain_unlock (domain);
7317 mono_loader_unlock ();
7321 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7322 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7325 if (!verify_safe_for_managed_space (type)) {
7326 mono_domain_unlock (domain);
7327 mono_loader_unlock ();
7328 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7332 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7333 gboolean is_type_done = TRUE;
7334 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7335 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7336 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7338 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7339 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7341 if (gparam->owner && gparam->owner->is_method) {
7342 MonoMethod *method = gparam->owner->owner.method;
7343 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7344 is_type_done = FALSE;
7345 } else if (gparam->owner && !gparam->owner->is_method) {
7346 MonoClass *klass = gparam->owner->owner.klass;
7347 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7348 is_type_done = FALSE;
7352 /* g_assert_not_reached (); */
7353 /* should this be considered an error condition? */
7354 if (is_type_done && !type->byref) {
7355 mono_domain_unlock (domain);
7356 mono_loader_unlock ();
7357 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7360 /* This is stored in vtables/JITted code so it has to be pinned */
7361 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7362 if (!mono_error_ok (error))
7366 mono_g_hash_table_insert (domain->type_hash, type, res);
7368 if (type->type == MONO_TYPE_VOID)
7369 domain->typeof_void = (MonoObject*)res;
7371 mono_domain_unlock (domain);
7372 mono_loader_unlock ();
7377 * mono_method_get_object:
7378 * @domain: an app domain
7380 * @refclass: the reflected type (can be NULL)
7382 * Return an System.Reflection.MonoMethod object representing the method @method.
7384 MonoReflectionMethod*
7385 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7388 MonoReflectionMethod *ret = NULL;
7389 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7390 mono_error_cleanup (&error);
7395 * mono_method_get_object_checked:
7396 * @domain: an app domain
7398 * @refclass: the reflected type (can be NULL)
7399 * @error: set on error.
7401 * Return an System.Reflection.MonoMethod object representing the method @method.
7402 * Returns NULL and sets @error on error.
7404 MonoReflectionMethod*
7405 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7408 * We use the same C representation for methods and constructors, but the type
7409 * name in C# is different.
7411 MonoReflectionType *rt;
7413 MonoReflectionMethod *ret;
7415 mono_error_init (error);
7417 if (method->is_inflated) {
7418 MonoReflectionGenericMethod *gret;
7421 refclass = method->klass;
7422 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7423 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7424 klass = mono_class_get_mono_generic_cmethod_class ();
7426 klass = mono_class_get_mono_generic_method_class ();
7428 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7429 if (!mono_error_ok (error))
7431 gret->method.method = method;
7433 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7435 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7436 if (!mono_error_ok (error))
7439 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7441 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7445 refclass = method->klass;
7447 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7448 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7449 klass = mono_class_get_mono_cmethod_class ();
7452 klass = mono_class_get_mono_method_class ();
7454 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7455 if (!mono_error_ok (error))
7457 ret->method = method;
7459 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7460 if (!mono_error_ok (error))
7463 MONO_OBJECT_SETREF (ret, reftype, rt);
7465 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7468 g_assert (!mono_error_ok (error));
7473 * mono_method_clear_object:
7475 * Clear the cached reflection objects for the dynamic method METHOD.
7478 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7481 g_assert (method_is_dynamic (method));
7483 klass = method->klass;
7485 clear_cached_object (domain, method, klass);
7486 klass = klass->parent;
7488 /* Added by mono_param_get_objects () */
7489 clear_cached_object (domain, &(method->signature), NULL);
7490 klass = method->klass;
7492 clear_cached_object (domain, &(method->signature), klass);
7493 klass = klass->parent;
7498 * mono_field_get_object:
7499 * @domain: an app domain
7503 * Return an System.Reflection.MonoField object representing the field @field
7506 MonoReflectionField*
7507 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7510 MonoReflectionField *result;
7511 result = mono_field_get_object_checked (domain, klass, field, &error);
7512 mono_error_cleanup (&error);
7517 * mono_field_get_object_checked:
7518 * @domain: an app domain
7521 * @error: set on error
7523 * Return an System.Reflection.MonoField object representing the field @field
7524 * in class @klass. On error, returns NULL and sets @error.
7526 MonoReflectionField*
7527 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7529 MonoReflectionType *rt;
7530 MonoReflectionField *res;
7532 mono_error_init (error);
7534 CHECK_OBJECT (MonoReflectionField *, field, klass);
7535 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7540 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7542 if (is_field_on_inst (field)) {
7543 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7545 rt = mono_type_get_object_checked (domain, field->type, error);
7546 if (!mono_error_ok (error))
7549 MONO_OBJECT_SETREF (res, type, rt);
7552 rt = mono_type_get_object_checked (domain, field->type, error);
7553 if (!mono_error_ok (error))
7556 MONO_OBJECT_SETREF (res, type, rt);
7558 res->attrs = mono_field_get_flags (field);
7560 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7564 * mono_property_get_object:
7565 * @domain: an app domain
7567 * @property: a property
7569 * Return an System.Reflection.MonoProperty object representing the property @property
7572 MonoReflectionProperty*
7573 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7576 MonoReflectionProperty *result;
7577 result = mono_property_get_object_checked (domain, klass, property, &error);
7578 mono_error_cleanup (&error);
7583 * mono_property_get_object:
7584 * @domain: an app domain
7586 * @property: a property
7587 * @error: set on error
7589 * Return an System.Reflection.MonoProperty object representing the property @property
7590 * in class @klass. On error returns NULL and sets @error.
7592 MonoReflectionProperty*
7593 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7595 MonoReflectionProperty *res;
7597 mono_error_init (error);
7599 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7600 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7604 res->property = property;
7605 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7609 * mono_event_get_object:
7610 * @domain: an app domain
7614 * Return an System.Reflection.MonoEvent object representing the event @event
7617 MonoReflectionEvent*
7618 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7621 MonoReflectionEvent *result;
7622 result = mono_event_get_object_checked (domain, klass, event, &error);
7623 mono_error_cleanup (&error);
7628 * mono_event_get_object_checked:
7629 * @domain: an app domain
7632 * @error: set on error
7634 * Return an System.Reflection.MonoEvent object representing the event @event
7635 * in class @klass. On failure sets @error and returns NULL
7637 MonoReflectionEvent*
7638 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7640 MonoReflectionEvent *res;
7641 MonoReflectionMonoEvent *mono_event;
7643 mono_error_init (error);
7644 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7645 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7648 mono_event->klass = klass;
7649 mono_event->event = event;
7650 res = (MonoReflectionEvent*)mono_event;
7651 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7655 * mono_get_reflection_missing_object:
7656 * @domain: Domain where the object lives
7658 * Returns the System.Reflection.Missing.Value singleton object
7659 * (of type System.Reflection.Missing).
7661 * Used as the value for ParameterInfo.DefaultValue when Optional
7665 mono_get_reflection_missing_object (MonoDomain *domain)
7669 static MonoClassField *missing_value_field = NULL;
7671 if (!missing_value_field) {
7672 MonoClass *missing_klass;
7673 missing_klass = mono_class_get_missing_class ();
7674 mono_class_init (missing_klass);
7675 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7676 g_assert (missing_value_field);
7678 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7679 mono_error_assert_ok (&error);
7684 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7687 *dbnull = mono_get_dbnull_object (domain);
7692 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7694 if (!*reflection_missing)
7695 *reflection_missing = mono_get_reflection_missing_object (domain);
7696 return *reflection_missing;
7700 * mono_param_get_objects:
7701 * @domain: an app domain
7704 * Return an System.Reflection.ParameterInfo array object representing the parameters
7705 * in the method @method.
7708 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7710 static MonoClass *System_Reflection_ParameterInfo;
7711 static MonoClass *System_Reflection_ParameterInfo_array;
7712 MonoArray *res = NULL;
7713 MonoReflectionMethod *member = NULL;
7714 MonoReflectionParameter *param = NULL;
7715 char **names = NULL, **blobs = NULL;
7716 guint32 *types = NULL;
7717 MonoType *type = NULL;
7718 MonoObject *dbnull = NULL;
7719 MonoObject *missing = NULL;
7720 MonoMarshalSpec **mspecs = NULL;
7721 MonoMethodSignature *sig = NULL;
7722 MonoVTable *pinfo_vtable;
7723 MonoReflectionType *rt;
7726 mono_error_init (error);
7728 if (!System_Reflection_ParameterInfo_array) {
7731 klass = mono_class_get_mono_parameter_info_class ();
7733 mono_memory_barrier ();
7734 System_Reflection_ParameterInfo = klass;
7737 klass = mono_array_class_get (klass, 1);
7738 mono_memory_barrier ();
7739 System_Reflection_ParameterInfo_array = klass;
7742 sig = mono_method_signature_checked (method, error);
7743 if (!mono_error_ok (error))
7746 if (!sig->param_count) {
7747 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7754 /* Note: the cache is based on the address of the signature into the method
7755 * since we already cache MethodInfos with the method as keys.
7757 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7759 member = mono_method_get_object_checked (domain, method, refclass, error);
7762 names = g_new (char *, sig->param_count);
7763 mono_method_get_param_names (method, (const char **) names);
7765 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7766 mono_method_get_marshal_info (method, mspecs);
7768 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7772 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7773 for (i = 0; i < sig->param_count; ++i) {
7774 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7778 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7782 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7784 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7786 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7788 param->PositionImpl = i;
7789 param->AttrsImpl = sig->params [i]->attrs;
7791 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7792 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7793 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7795 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7799 blobs = g_new0 (char *, sig->param_count);
7800 types = g_new0 (guint32, sig->param_count);
7801 get_default_param_value_blobs (method, blobs, types);
7804 /* Build MonoType for the type from the Constant Table */
7806 type = g_new0 (MonoType, 1);
7807 type->type = (MonoTypeEnum)types [i];
7808 type->data.klass = NULL;
7809 if (types [i] == MONO_TYPE_CLASS)
7810 type->data.klass = mono_defaults.object_class;
7811 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7812 /* For enums, types [i] contains the base type */
7814 type->type = MONO_TYPE_VALUETYPE;
7815 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7817 type->data.klass = mono_class_from_mono_type (type);
7819 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7822 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7824 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7825 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7826 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7827 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7829 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7834 if (mspecs [i + 1]) {
7835 MonoReflectionMarshalAsAttribute* mobj;
7836 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7839 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7842 mono_array_setref (res, i, param);
7852 for (i = sig->param_count; i >= 0; i--) {
7854 mono_metadata_free_marshal_spec (mspecs [i]);
7862 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7866 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7869 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7870 mono_error_assert_ok (&error);
7875 * mono_method_body_get_object:
7876 * @domain: an app domain
7879 * Return an System.Reflection.MethodBody object representing the method @method.
7881 MonoReflectionMethodBody*
7882 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7885 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7886 mono_error_cleanup (&error);
7891 * mono_method_body_get_object_checked:
7892 * @domain: an app domain
7894 * @error: set on error
7896 * Return an System.Reflection.MethodBody object representing the
7897 * method @method. On failure, returns NULL and sets @error.
7899 MonoReflectionMethodBody*
7900 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7902 MonoReflectionMethodBody *ret;
7903 MonoMethodHeader *header;
7905 MonoReflectionType *rt;
7906 guint32 method_rva, local_var_sig_token;
7908 unsigned char format, flags;
7911 mono_error_init (error);
7913 /* for compatibility with .net */
7914 if (method_is_dynamic (method)) {
7915 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7919 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7921 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7922 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7923 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7924 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7925 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7928 image = method->klass->image;
7929 header = mono_method_get_header_checked (method, error);
7930 return_val_if_nok (error, NULL);
7932 if (!image_is_dynamic (image)) {
7933 /* Obtain local vars signature token */
7934 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7935 ptr = mono_image_rva_map (image, method_rva);
7936 flags = *(const unsigned char *) ptr;
7937 format = flags & METHOD_HEADER_FORMAT_MASK;
7939 case METHOD_HEADER_TINY_FORMAT:
7940 local_var_sig_token = 0;
7942 case METHOD_HEADER_FAT_FORMAT:
7946 local_var_sig_token = read32 (ptr);
7949 g_assert_not_reached ();
7952 local_var_sig_token = 0; //FIXME
7954 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7958 ret->init_locals = header->init_locals;
7959 ret->max_stack = header->max_stack;
7960 ret->local_var_sig_token = local_var_sig_token;
7961 MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7964 MONO_OBJECT_SETREF (ret, il, il_arr);
7965 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7968 MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7971 MONO_OBJECT_SETREF (ret, locals, locals_arr);
7972 for (i = 0; i < header->num_locals; ++i) {
7973 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7977 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7981 MONO_OBJECT_SETREF (info, local_type, rt);
7983 info->is_pinned = header->locals [i]->pinned;
7984 info->local_index = i;
7985 mono_array_setref (ret->locals, i, info);
7989 MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7992 MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7993 for (i = 0; i < header->num_clauses; ++i) {
7994 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7997 MonoExceptionClause *clause = &header->clauses [i];
7999 info->flags = clause->flags;
8000 info->try_offset = clause->try_offset;
8001 info->try_length = clause->try_len;
8002 info->handler_offset = clause->handler_offset;
8003 info->handler_length = clause->handler_len;
8004 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8005 info->filter_offset = clause->data.filter_offset;
8006 else if (clause->data.catch_class) {
8007 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
8011 MONO_OBJECT_SETREF (info, catch_type, rt);
8014 mono_array_setref (ret->clauses, i, info);
8017 mono_metadata_free_mh (header);
8018 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
8022 mono_metadata_free_mh (header);
8027 * mono_get_dbnull_object:
8028 * @domain: Domain where the object lives
8030 * Returns the System.DBNull.Value singleton object
8032 * Used as the value for ParameterInfo.DefaultValue
8035 mono_get_dbnull_object (MonoDomain *domain)
8039 static MonoClassField *dbnull_value_field = NULL;
8041 if (!dbnull_value_field) {
8042 MonoClass *dbnull_klass;
8043 dbnull_klass = mono_class_get_dbnull_class ();
8044 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8045 g_assert (dbnull_value_field);
8047 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8048 mono_error_assert_ok (&error);
8053 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8055 guint32 param_index, i, lastp, crow = 0;
8056 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8059 MonoClass *klass = method->klass;
8060 MonoImage *image = klass->image;
8061 MonoMethodSignature *methodsig = mono_method_signature (method);
8063 MonoTableInfo *constt;
8064 MonoTableInfo *methodt;
8065 MonoTableInfo *paramt;
8067 if (!methodsig->param_count)
8070 mono_class_init (klass);
8072 if (image_is_dynamic (klass->image)) {
8073 MonoReflectionMethodAux *aux;
8074 if (method->is_inflated)
8075 method = ((MonoMethodInflated*)method)->declaring;
8076 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8077 if (aux && aux->param_defaults) {
8078 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8079 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8084 methodt = &klass->image->tables [MONO_TABLE_METHOD];
8085 paramt = &klass->image->tables [MONO_TABLE_PARAM];
8086 constt = &image->tables [MONO_TABLE_CONSTANT];
8088 idx = mono_method_get_index (method) - 1;
8089 g_assert (idx != -1);
8091 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8092 if (idx + 1 < methodt->rows)
8093 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8095 lastp = paramt->rows + 1;
8097 for (i = param_index; i < lastp; ++i) {
8100 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8101 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8103 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8106 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8111 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8112 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8113 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8120 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8125 MonoType *basetype = type;
8127 mono_error_init (error);
8132 klass = mono_class_from_mono_type (type);
8133 if (klass->valuetype) {
8134 object = mono_object_new_checked (domain, klass, error);
8135 return_val_if_nok (error, NULL);
8136 retval = ((gchar *) object + sizeof (MonoObject));
8137 if (klass->enumtype)
8138 basetype = mono_class_enum_basetype (klass);
8143 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
8150 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8153 gboolean quoted = FALSE;
8155 memset (assembly, 0, sizeof (MonoAssemblyName));
8156 assembly->culture = "";
8157 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8164 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8175 /* Remove trailing whitespace */
8177 while (*s && g_ascii_isspace (*s))
8180 while (g_ascii_isspace (*p))
8183 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8185 assembly->major = strtoul (p, &s, 10);
8186 if (s == p || *s != '.')
8189 assembly->minor = strtoul (p, &s, 10);
8190 if (s == p || *s != '.')
8193 assembly->build = strtoul (p, &s, 10);
8194 if (s == p || *s != '.')
8197 assembly->revision = strtoul (p, &s, 10);
8201 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8203 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8204 assembly->culture = "";
8207 assembly->culture = p;
8208 while (*p && *p != ',') {
8212 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8214 if (strncmp (p, "null", 4) == 0) {
8219 while (*p && *p != ',') {
8222 len = (p - start + 1);
8223 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8224 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8225 g_strlcpy ((char*)assembly->public_key_token, start, len);
8228 while (*p && *p != ',')
8232 while (g_ascii_isspace (*p) || *p == ',') {
8246 * mono_reflection_parse_type:
8249 * Parse a type name as accepted by the GetType () method and output the info
8250 * extracted in the info structure.
8251 * the name param will be mangled, so, make a copy before passing it to this function.
8252 * The fields in info will be valid until the memory pointed to by name is valid.
8254 * See also mono_type_get_name () below.
8256 * Returns: 0 on parse error.
8259 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8260 MonoTypeNameParse *info)
8262 char *start, *p, *w, *last_point, *startn;
8263 int in_modifiers = 0;
8264 int isbyref = 0, rank = 0, isptr = 0;
8266 start = p = w = name;
8268 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8269 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8270 info->name = info->name_space = NULL;
8271 info->nested = NULL;
8272 info->modifiers = NULL;
8273 info->type_arguments = NULL;
8275 /* last_point separates the namespace from the name */
8278 while (*p == ' ') p++, start++, w++, name++;
8283 *p = 0; /* NULL terminate the name */
8285 info->nested = g_list_append (info->nested, startn);
8286 /* we have parsed the nesting namespace + name */
8290 info->name_space = start;
8292 info->name = last_point + 1;
8294 info->name_space = (char *)"";
8322 info->name_space = start;
8324 info->name = last_point + 1;
8326 info->name_space = (char *)"";
8333 if (isbyref) /* only one level allowed by the spec */
8337 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8341 if (isbyref) /* pointer to ref not okay */
8343 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8348 if (isbyref) /* array of ref and generic ref are not okay */
8350 //Decide if it's an array of a generic argument list
8355 if (*p == ',' || *p == '*' || *p == ']') { //array
8363 else if (*p == '*') /* '*' means unknown lower bound */
8364 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8371 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8373 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8376 info->type_arguments = g_ptr_array_new ();
8378 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8379 gboolean fqname = FALSE;
8381 g_ptr_array_add (info->type_arguments, subinfo);
8383 while (*p == ' ') p++;
8389 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8392 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8393 if (fqname && (*p != ']')) {
8401 while (*p && (*p != ']'))
8409 if (g_ascii_isspace (*aname)) {
8416 !assembly_name_to_aname (&subinfo->assembly, aname))
8418 } else if (fqname && (*p == ']')) {
8440 if (g_ascii_isspace (*p)) {
8447 return 0; /* missing assembly name */
8448 if (!assembly_name_to_aname (&info->assembly, p))
8454 if (info->assembly.name)
8457 // *w = 0; /* terminate class name */
8459 if (!info->name || !*info->name)
8463 /* add other consistency checks */
8469 * mono_identifier_unescape_type_name_chars:
8470 * @identifier: the display name of a mono type
8473 * The name in internal form, that is without escaping backslashes.
8475 * The string is modified in place!
8478 mono_identifier_unescape_type_name_chars(char* identifier)
8483 for (w = r = identifier; *r != 0; r++)
8501 mono_identifier_unescape_info (MonoTypeNameParse* info);
8504 unescape_each_type_argument(void* data, void* user_data)
8506 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8507 mono_identifier_unescape_info (info);
8511 unescape_each_nested_name (void* data, void* user_data)
8513 char* nested_name = (char*) data;
8514 mono_identifier_unescape_type_name_chars(nested_name);
8518 * mono_identifier_unescape_info:
8520 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8524 * Destructively updates the info by unescaping the identifiers that
8525 * comprise the type namespace, name, nested types (if any) and
8526 * generic type arguments (if any).
8528 * The resulting info has the names in internal form.
8532 mono_identifier_unescape_info (MonoTypeNameParse *info)
8536 mono_identifier_unescape_type_name_chars(info->name_space);
8537 mono_identifier_unescape_type_name_chars(info->name);
8538 // but don't escape info->assembly
8539 if (info->type_arguments)
8540 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8542 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8546 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8548 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8550 mono_identifier_unescape_info (info);
8556 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8558 gboolean type_resolve = FALSE;
8560 MonoImage *rootimage = image;
8562 mono_error_init (error);
8564 if (info->assembly.name) {
8565 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8566 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8568 * This could happen in the AOT compiler case when the search hook is not
8571 assembly = image->assembly;
8573 /* then we must load the assembly ourselve - see #60439 */
8574 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8578 image = assembly->image;
8579 } else if (!image) {
8580 image = mono_defaults.corlib;
8583 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8584 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8585 /* ignore the error and try again */
8586 mono_error_cleanup (error);
8587 mono_error_init (error);
8588 image = mono_defaults.corlib;
8589 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8596 * mono_reflection_get_type_internal:
8598 * Returns: may return NULL on success, sets error on failure.
8601 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8606 gboolean bounded = FALSE;
8608 mono_error_init (error);
8610 image = mono_defaults.corlib;
8613 rootimage = mono_defaults.corlib;
8616 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8618 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8623 for (mod = info->nested; mod; mod = mod->next) {
8624 gpointer iter = NULL;
8628 mono_class_init (parent);
8630 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8632 char *nested_name, *nested_nspace;
8633 gboolean match = TRUE;
8635 lastp = strrchr ((const char *)mod->data, '.');
8637 /* Nested classes can have namespaces */
8640 nested_name = g_strdup (lastp + 1);
8641 nspace_len = lastp - (char*)mod->data;
8642 nested_nspace = (char *)g_malloc (nspace_len + 1);
8643 memcpy (nested_nspace, mod->data, nspace_len);
8644 nested_nspace [nspace_len] = '\0';
8647 nested_name = (char *)mod->data;
8648 nested_nspace = NULL;
8651 if (nested_nspace) {
8653 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8656 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8662 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8665 if (strcmp (klass->name, nested_name) != 0)
8670 g_free (nested_name);
8671 g_free (nested_nspace);
8683 if (info->type_arguments) {
8684 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8685 MonoReflectionType *the_type;
8689 for (i = 0; i < info->type_arguments->len; i++) {
8690 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8692 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8693 if (!type_args [i]) {
8699 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8703 instance = mono_reflection_bind_generic_parameters (
8704 the_type, info->type_arguments->len, type_args, error);
8710 klass = mono_class_from_mono_type (instance);
8713 for (mod = info->modifiers; mod; mod = mod->next) {
8714 modval = GPOINTER_TO_UINT (mod->data);
8715 if (!modval) { /* byref: must be last modifier */
8716 return &klass->this_arg;
8717 } else if (modval == -1) {
8718 klass = mono_ptr_class_get (&klass->byval_arg);
8719 } else if (modval == -2) {
8721 } else { /* array rank */
8722 klass = mono_bounded_array_class_get (klass, modval, bounded);
8726 return &klass->byval_arg;
8730 * mono_reflection_get_type:
8731 * @image: a metadata context
8732 * @info: type description structure
8733 * @ignorecase: flag for case-insensitive string compares
8734 * @type_resolve: whenever type resolve was already tried
8736 * Build a MonoType from the type description in @info.
8741 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8743 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8744 mono_error_cleanup (&error);
8749 * mono_reflection_get_type_checked:
8750 * @rootimage: the image of the currently active managed caller
8751 * @image: a metadata context
8752 * @info: type description structure
8753 * @ignorecase: flag for case-insensitive string compares
8754 * @type_resolve: whenever type resolve was already tried
8755 * @error: set on error.
8757 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8761 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8762 mono_error_init (error);
8763 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8768 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8770 MonoReflectionAssemblyBuilder *abuilder;
8774 mono_error_init (error);
8775 g_assert (assembly_is_dynamic (assembly));
8776 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8780 /* Enumerate all modules */
8783 if (abuilder->modules) {
8784 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8785 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8786 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8789 if (!mono_error_ok (error))
8794 if (!type && abuilder->loaded_modules) {
8795 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8796 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8797 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8800 if (!mono_error_ok (error))
8809 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8812 MonoReflectionAssembly *assembly;
8816 mono_error_init (error);
8818 if (image && image_is_dynamic (image))
8819 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8821 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8823 return_val_if_nok (error, NULL);
8827 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8834 *type_resolve = TRUE;
8837 /* Reconstruct the type name */
8838 fullName = g_string_new ("");
8839 if (info->name_space && (info->name_space [0] != '\0'))
8840 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8842 g_string_printf (fullName, "%s", info->name);
8843 for (mod = info->nested; mod; mod = mod->next)
8844 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8846 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8847 if (!is_ok (error)) {
8848 g_string_free (fullName, TRUE);
8853 if (assembly_is_dynamic (assembly->assembly))
8854 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8855 info, ignorecase, error);
8857 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8858 info, ignorecase, error);
8860 g_string_free (fullName, TRUE);
8861 return_val_if_nok (error, NULL);
8866 mono_reflection_free_type_info (MonoTypeNameParse *info)
8868 g_list_free (info->modifiers);
8869 g_list_free (info->nested);
8871 if (info->type_arguments) {
8874 for (i = 0; i < info->type_arguments->len; i++) {
8875 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8877 mono_reflection_free_type_info (subinfo);
8878 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8882 g_ptr_array_free (info->type_arguments, TRUE);
8887 * mono_reflection_type_from_name:
8889 * @image: a metadata context (can be NULL).
8891 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8892 * it defaults to get the type from @image or, if @image is NULL or loading
8893 * from it fails, uses corlib.
8897 mono_reflection_type_from_name (char *name, MonoImage *image)
8900 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8901 mono_error_cleanup (&error);
8906 * mono_reflection_type_from_name_checked:
8908 * @image: a metadata context (can be NULL).
8909 * @error: set on errror.
8911 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8912 * it defaults to get the type from @image or, if @image is NULL or loading
8913 * from it fails, uses corlib. On failure returns NULL and sets @error.
8917 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8919 MonoType *type = NULL;
8920 MonoTypeNameParse info;
8923 mono_error_init (error);
8924 /* Make a copy since parse_type modifies its argument */
8925 tmp = g_strdup (name);
8927 /*g_print ("requested type %s\n", str);*/
8928 if (mono_reflection_parse_type (tmp, &info)) {
8929 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8930 if (!is_ok (error)) {
8932 mono_reflection_free_type_info (&info);
8938 mono_reflection_free_type_info (&info);
8943 * mono_reflection_get_token:
8945 * Return the metadata token of OBJ which should be an object
8946 * representing a metadata element.
8949 mono_reflection_get_token (MonoObject *obj)
8952 guint32 result = mono_reflection_get_token_checked (obj, &error);
8953 mono_error_assert_ok (&error);
8958 * mono_reflection_get_token_checked:
8960 * @error: set on error
8962 * Return the metadata token of @obj which should be an object
8963 * representing a metadata element. On failure sets @error.
8966 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8971 mono_error_init (error);
8973 klass = obj->vtable->klass;
8975 if (strcmp (klass->name, "MethodBuilder") == 0) {
8976 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8978 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8979 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8980 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8982 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8983 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8984 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8986 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8987 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8988 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8989 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8990 } else if (strcmp (klass->name, "RuntimeType") == 0) {
8991 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8992 return_val_if_nok (error, 0);
8993 MonoClass *mc = mono_class_from_mono_type (type);
8994 if (!mono_class_init (mc)) {
8995 mono_error_set_for_class_failure (error, mc);
8999 token = mc->type_token;
9000 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
9001 strcmp (klass->name, "MonoMethod") == 0 ||
9002 strcmp (klass->name, "MonoGenericMethod") == 0 ||
9003 strcmp (klass->name, "MonoGenericCMethod") == 0) {
9004 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
9005 if (m->method->is_inflated) {
9006 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
9007 return inflated->declaring->token;
9009 token = m->method->token;
9011 } else if (strcmp (klass->name, "MonoField") == 0) {
9012 MonoReflectionField *f = (MonoReflectionField*)obj;
9014 if (is_field_on_inst (f->field)) {
9015 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
9017 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
9018 int field_index = f->field - dgclass->fields;
9021 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
9022 obj = dgclass->field_objects [field_index];
9023 return mono_reflection_get_token_checked (obj, error);
9026 token = mono_class_get_field_token (f->field);
9027 } else if (strcmp (klass->name, "MonoProperty") == 0) {
9028 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
9030 token = mono_class_get_property_token (p->property);
9031 } else if (strcmp (klass->name, "MonoEvent") == 0) {
9032 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
9034 token = mono_class_get_event_token (p->event);
9035 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
9036 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
9037 MonoClass *member_class = mono_object_class (p->MemberImpl);
9038 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
9040 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
9041 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
9042 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9045 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9046 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9048 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9049 klass->name_space, klass->name);
9057 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
9058 * The @is_enum flag only affects the error message that's displayed on failure.
9061 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9063 MonoError inner_error;
9064 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9066 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9067 "Could not load %s %s while decoding custom attribute: %s",
9068 is_enum ? "enum type": "type",
9070 mono_error_get_message (&inner_error));
9071 mono_error_cleanup (&inner_error);
9078 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9082 int slen = mono_metadata_decode_value (p, &p);
9084 mono_error_init (error);
9086 n = (char *)g_memdup (p, slen + 1);
9088 t = cattr_type_from_name (n, image, TRUE, error);
9090 return_val_if_nok (error, NULL);
9093 return mono_class_from_mono_type (t);
9097 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9099 int slen, type = t->type;
9100 MonoClass *tklass = t->data.klass;
9102 mono_error_init (error);
9108 case MONO_TYPE_BOOLEAN: {
9109 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9114 case MONO_TYPE_CHAR:
9116 case MONO_TYPE_I2: {
9117 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9122 #if SIZEOF_VOID_P == 4
9128 case MONO_TYPE_I4: {
9129 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9134 #if SIZEOF_VOID_P == 8
9135 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9139 case MONO_TYPE_I8: {
9140 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9145 case MONO_TYPE_R8: {
9146 double *val = (double *)g_malloc (sizeof (double));
9151 case MONO_TYPE_VALUETYPE:
9152 if (t->data.klass->enumtype) {
9153 type = mono_class_enum_basetype (t->data.klass)->type;
9156 MonoClass *k = t->data.klass;
9158 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9159 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9165 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9168 case MONO_TYPE_STRING:
9169 if (*p == (char)0xFF) {
9173 slen = mono_metadata_decode_value (p, &p);
9175 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9176 case MONO_TYPE_CLASS: {
9177 MonoReflectionType *rt;
9180 if (*p == (char)0xFF) {
9185 slen = mono_metadata_decode_value (p, &p);
9186 n = (char *)g_memdup (p, slen + 1);
9188 t = cattr_type_from_name (n, image, FALSE, error);
9190 return_val_if_nok (error, NULL);
9193 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9194 if (!mono_error_ok (error))
9199 case MONO_TYPE_OBJECT: {
9202 MonoClass *subc = NULL;
9207 } else if (subt == 0x0E) {
9208 type = MONO_TYPE_STRING;
9210 } else if (subt == 0x1D) {
9211 MonoType simple_type = {{0}};
9215 type = MONO_TYPE_SZARRAY;
9216 if (etype == 0x50) {
9217 tklass = mono_defaults.systemtype_class;
9218 } else if (etype == 0x55) {
9219 tklass = load_cattr_enum_type (image, p, &p, error);
9220 if (!mono_error_ok (error))
9224 /* See Partition II, Appendix B3 */
9225 etype = MONO_TYPE_OBJECT;
9226 simple_type.type = (MonoTypeEnum)etype;
9227 tklass = mono_class_from_mono_type (&simple_type);
9230 } else if (subt == 0x55) {
9233 slen = mono_metadata_decode_value (p, &p);
9234 n = (char *)g_memdup (p, slen + 1);
9236 t = cattr_type_from_name (n, image, FALSE, error);
9238 return_val_if_nok (error, NULL);
9240 subc = mono_class_from_mono_type (t);
9241 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9242 MonoType simple_type = {{0}};
9243 simple_type.type = (MonoTypeEnum)subt;
9244 subc = mono_class_from_mono_type (&simple_type);
9246 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9248 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9250 if (mono_error_ok (error)) {
9251 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9252 g_assert (!subc->has_references);
9253 if (mono_error_ok (error))
9254 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9260 case MONO_TYPE_SZARRAY: {
9262 guint32 i, alen, basetype;
9265 if (alen == 0xffffffff) {
9269 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9270 return_val_if_nok (error, NULL);
9271 basetype = tklass->byval_arg.type;
9272 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9273 basetype = mono_class_enum_basetype (tklass)->type;
9278 case MONO_TYPE_BOOLEAN:
9279 for (i = 0; i < alen; i++) {
9280 MonoBoolean val = *p++;
9281 mono_array_set (arr, MonoBoolean, i, val);
9284 case MONO_TYPE_CHAR:
9287 for (i = 0; i < alen; i++) {
9288 guint16 val = read16 (p);
9289 mono_array_set (arr, guint16, i, val);
9296 for (i = 0; i < alen; i++) {
9297 guint32 val = read32 (p);
9298 mono_array_set (arr, guint32, i, val);
9303 for (i = 0; i < alen; i++) {
9306 mono_array_set (arr, double, i, val);
9312 for (i = 0; i < alen; i++) {
9313 guint64 val = read64 (p);
9314 mono_array_set (arr, guint64, i, val);
9318 case MONO_TYPE_CLASS:
9319 case MONO_TYPE_OBJECT:
9320 case MONO_TYPE_STRING:
9321 case MONO_TYPE_SZARRAY:
9322 for (i = 0; i < alen; i++) {
9323 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9324 if (!mono_error_ok (error))
9326 mono_array_setref (arr, i, item);
9330 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9336 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9342 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9344 mono_error_init (error);
9346 gboolean is_ref = type_is_reference (t);
9348 void *val = load_cattr_value (image, t, p, end, error);
9349 if (!is_ok (error)) {
9356 return (MonoObject*)val;
9358 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9364 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9366 static MonoMethod *ctor;
9368 void *params [2], *unboxed;
9370 mono_error_init (error);
9373 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9375 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9376 return_val_if_nok (error, NULL);
9379 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9380 return_val_if_nok (error, NULL);
9381 unboxed = mono_object_unbox (retval);
9383 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9384 return_val_if_nok (error, NULL);
9390 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9392 static MonoMethod *ctor;
9394 void *unboxed, *params [2];
9396 mono_error_init (error);
9399 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9402 params [1] = typedarg;
9403 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9404 return_val_if_nok (error, NULL);
9406 unboxed = mono_object_unbox (retval);
9408 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9409 return_val_if_nok (error, NULL);
9415 type_is_reference (MonoType *type)
9417 switch (type->type) {
9418 case MONO_TYPE_BOOLEAN:
9419 case MONO_TYPE_CHAR:
9432 case MONO_TYPE_VALUETYPE:
9440 free_param_data (MonoMethodSignature *sig, void **params) {
9442 for (i = 0; i < sig->param_count; ++i) {
9443 if (!type_is_reference (sig->params [i]))
9444 g_free (params [i]);
9449 * Find the field index in the metadata FieldDef table.
9452 find_field_index (MonoClass *klass, MonoClassField *field) {
9455 for (i = 0; i < klass->field.count; ++i) {
9456 if (field == &klass->fields [i])
9457 return klass->field.first + 1 + i;
9463 * Find the property index in the metadata Property table.
9466 find_property_index (MonoClass *klass, MonoProperty *property) {
9469 for (i = 0; i < klass->ext->property.count; ++i) {
9470 if (property == &klass->ext->properties [i])
9471 return klass->ext->property.first + 1 + i;
9477 * Find the event index in the metadata Event table.
9480 find_event_index (MonoClass *klass, MonoEvent *event) {
9483 for (i = 0; i < klass->ext->event.count; ++i) {
9484 if (event == &klass->ext->events [i])
9485 return klass->ext->event.first + 1 + i;
9491 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9493 const char *p = (const char*)data;
9495 guint32 i, j, num_named;
9497 void *params_buf [32];
9498 void **params = NULL;
9499 MonoMethodSignature *sig;
9501 mono_error_init (error);
9503 mono_class_init (method->klass);
9505 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9506 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9511 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9512 if (!mono_error_ok (error)) return NULL;
9514 mono_runtime_invoke_checked (method, attr, NULL, error);
9515 if (!mono_error_ok (error))
9521 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9524 /*g_print ("got attr %s\n", method->klass->name);*/
9526 sig = mono_method_signature (method);
9527 if (sig->param_count < 32) {
9528 params = params_buf;
9529 memset (params, 0, sizeof (void*) * sig->param_count);
9531 /* Allocate using GC so it gets GC tracking */
9532 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9537 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9538 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9539 if (!mono_error_ok (error))
9544 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9545 if (!mono_error_ok (error)) goto fail;
9547 MonoObject *exc = NULL;
9548 mono_runtime_try_invoke (method, attr, params, &exc, error);
9549 if (!mono_error_ok (error))
9552 mono_error_set_exception_instance (error, (MonoException*)exc);
9556 num_named = read16 (named);
9558 for (j = 0; j < num_named; j++) {
9560 char *name, named_type, data_type;
9561 named_type = *named++;
9562 data_type = *named++; /* type of data */
9563 if (data_type == MONO_TYPE_SZARRAY)
9564 data_type = *named++;
9565 if (data_type == MONO_TYPE_ENUM) {
9568 type_len = mono_metadata_decode_blob_size (named, &named);
9569 type_name = (char *)g_malloc (type_len + 1);
9570 memcpy (type_name, named, type_len);
9571 type_name [type_len] = 0;
9573 /* FIXME: lookup the type and check type consistency */
9576 name_len = mono_metadata_decode_blob_size (named, &named);
9577 name = (char *)g_malloc (name_len + 1);
9578 memcpy (name, named, name_len);
9579 name [name_len] = 0;
9581 if (named_type == 0x53) {
9582 MonoClassField *field;
9585 /* how this fail is a blackbox */
9586 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9588 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9593 val = load_cattr_value (image, field->type, named, &named, error);
9594 if (!mono_error_ok (error)) {
9596 if (!type_is_reference (field->type))
9601 mono_field_set_value (attr, field, val);
9602 if (!type_is_reference (field->type))
9604 } else if (named_type == 0x54) {
9607 MonoType *prop_type;
9609 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9612 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9618 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9623 /* can we have more that 1 arg in a custom attr named property? */
9624 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9625 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9627 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9628 if (!mono_error_ok (error)) {
9630 if (!type_is_reference (prop_type))
9631 g_free (pparams [0]);
9636 mono_property_set_value_checked (prop, attr, pparams, error);
9637 if (!type_is_reference (prop_type))
9638 g_free (pparams [0]);
9639 if (!is_ok (error)) {
9647 free_param_data (method->signature, params);
9648 if (params != params_buf)
9649 mono_gc_free_fixed (params);
9654 free_param_data (method->signature, params);
9655 if (params != params_buf)
9656 mono_gc_free_fixed (params);
9661 * mono_reflection_create_custom_attr_data_args:
9663 * Create an array of typed and named arguments from the cattr blob given by DATA.
9664 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9665 * NAMED_ARG_INFO will contain information about the named arguments.
9668 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)
9670 MonoArray *typedargs, *namedargs;
9671 MonoClass *attrklass;
9673 const char *p = (const char*)data;
9675 guint32 i, j, num_named;
9676 CattrNamedArg *arginfo = NULL;
9680 *named_arg_info = NULL;
9682 mono_error_init (error);
9684 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9685 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9689 mono_class_init (method->klass);
9691 domain = mono_domain_get ();
9693 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9696 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9697 return_if_nok (error);
9701 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9704 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9705 return_if_nok (error);
9706 mono_array_setref (typedargs, i, obj);
9710 num_named = read16 (named);
9711 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9712 return_if_nok (error);
9714 attrklass = method->klass;
9716 arginfo = g_new0 (CattrNamedArg, num_named);
9717 *named_arg_info = arginfo;
9719 for (j = 0; j < num_named; j++) {
9721 char *name, named_type, data_type;
9722 named_type = *named++;
9723 data_type = *named++; /* type of data */
9724 if (data_type == MONO_TYPE_SZARRAY)
9725 data_type = *named++;
9726 if (data_type == MONO_TYPE_ENUM) {
9729 type_len = mono_metadata_decode_blob_size (named, &named);
9730 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9733 type_name = (char *)g_malloc (type_len + 1);
9734 memcpy (type_name, named, type_len);
9735 type_name [type_len] = 0;
9737 /* FIXME: lookup the type and check type consistency */
9740 name_len = mono_metadata_decode_blob_size (named, &named);
9741 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9743 name = (char *)g_malloc (name_len + 1);
9744 memcpy (name, named, name_len);
9745 name [name_len] = 0;
9747 if (named_type == 0x53) {
9749 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9756 arginfo [j].type = field->type;
9757 arginfo [j].field = field;
9759 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9760 if (!is_ok (error)) {
9764 mono_array_setref (namedargs, j, obj);
9766 } else if (named_type == 0x54) {
9768 MonoType *prop_type;
9769 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9771 if (!prop || !prop->set) {
9776 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9777 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9779 arginfo [j].type = prop_type;
9780 arginfo [j].prop = prop;
9782 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9783 if (!is_ok (error)) {
9787 mono_array_setref (namedargs, j, obj);
9792 *typed_args = typedargs;
9793 *named_args = namedargs;
9796 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9798 *named_arg_info = NULL;
9802 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9805 MonoArray *typedargs, *namedargs;
9808 CattrNamedArg *arginfo = NULL;
9811 mono_error_init (error);
9819 image = assembly->assembly->image;
9820 method = ref_method->method;
9821 domain = mono_object_domain (ref_method);
9823 if (!mono_class_init (method->klass)) {
9824 mono_error_set_for_class_failure (error, method->klass);
9828 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9832 if (!typedargs || !namedargs)
9835 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9836 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9837 MonoObject *typedarg;
9839 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9842 mono_array_setref (typedargs, i, typedarg);
9845 for (i = 0; i < mono_array_length (namedargs); ++i) {
9846 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9847 MonoObject *typedarg, *namedarg, *minfo;
9849 if (arginfo [i].prop) {
9850 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9854 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9859 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9862 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9866 mono_array_setref (namedargs, i, namedarg);
9869 *ctor_args = typedargs;
9870 *named_args = namedargs;
9874 return mono_error_ok (error);
9878 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9881 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9882 mono_error_set_pending_exception (&error);
9886 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9888 static MonoMethod *ctor;
9894 mono_error_init (error);
9896 g_assert (image->assembly);
9899 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9901 domain = mono_domain_get ();
9902 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9903 return_val_if_nok (error, NULL);
9904 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9905 return_val_if_nok (error, NULL);
9906 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9907 return_val_if_nok (error, NULL);
9908 params [2] = (gpointer)&cattr->data;
9909 params [3] = &cattr->data_size;
9911 mono_runtime_invoke_checked (ctor, attr, params, error);
9912 return_val_if_nok (error, NULL);
9917 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9923 mono_error_init (error);
9925 for (i = 0; i < cinfo->num_attrs; ++i) {
9926 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
9927 if (!centry->ctor) {
9928 /* The cattr type is not finished yet */
9929 /* We should include the type name but cinfo doesn't contain it */
9930 mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
9937 for (i = 0; i < cinfo->num_attrs; ++i) {
9938 MonoMethod *ctor = cinfo->attrs[i].ctor;
9940 if (mono_class_is_assignable_from (attr_klass, ctor->klass))
9944 n = cinfo->num_attrs;
9947 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9948 return_val_if_nok (error, NULL);
9950 for (i = 0; i < cinfo->num_attrs; ++i) {
9951 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
9952 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
9953 attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
9954 if (!mono_error_ok (error))
9956 mono_array_setref (result, n, attr);
9964 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9967 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9968 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9974 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9980 mono_error_init (error);
9981 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9982 return_val_if_nok (error, NULL);
9983 for (i = 0; i < cinfo->num_attrs; ++i) {
9984 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9985 return_val_if_nok (error, NULL);
9986 mono_array_setref (result, i, attr);
9992 * mono_custom_attrs_from_index:
9994 * Returns: NULL if no attributes are found or if a loading error occurs.
9997 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
10000 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
10001 mono_error_cleanup (&error);
10005 * mono_custom_attrs_from_index_checked:
10007 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
10009 MonoCustomAttrInfo*
10010 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
10012 guint32 mtoken, i, len;
10013 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
10015 MonoCustomAttrInfo *ainfo;
10016 GList *tmp, *list = NULL;
10018 MonoCustomAttrEntry* attr;
10020 mono_error_init (error);
10022 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
10024 i = mono_metadata_custom_attrs_from_index (image, idx);
10028 while (i < ca->rows) {
10029 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
10031 list = g_list_prepend (list, GUINT_TO_POINTER (i));
10034 len = g_list_length (list);
10037 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
10038 ainfo->num_attrs = len;
10039 ainfo->image = image;
10040 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
10041 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
10042 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
10043 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
10044 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
10045 mtoken |= MONO_TOKEN_METHOD_DEF;
10047 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
10048 mtoken |= MONO_TOKEN_MEMBER_REF;
10051 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
10054 attr = &ainfo->attrs [i - 1];
10055 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10057 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10058 g_list_free (list);
10063 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10064 /*FIXME raising an exception here doesn't make any sense*/
10065 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10066 g_list_free (list);
10070 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10071 attr->data_size = mono_metadata_decode_value (data, &data);
10072 attr->data = (guchar*)data;
10074 g_list_free (list);
10079 MonoCustomAttrInfo*
10080 mono_custom_attrs_from_method (MonoMethod *method)
10083 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
10084 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10088 MonoCustomAttrInfo*
10089 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10093 mono_error_init (error);
10096 * An instantiated method has the same cattrs as the generic method definition.
10098 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10099 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10101 if (method->is_inflated)
10102 method = ((MonoMethodInflated *) method)->declaring;
10104 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10105 return lookup_custom_attr (method->klass->image, method);
10107 if (!method->token)
10108 /* Synthetic methods */
10111 idx = mono_method_get_index (method);
10112 idx <<= MONO_CUSTOM_ATTR_BITS;
10113 idx |= MONO_CUSTOM_ATTR_METHODDEF;
10114 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10117 MonoCustomAttrInfo*
10118 mono_custom_attrs_from_class (MonoClass *klass)
10121 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10122 mono_error_cleanup (&error);
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10131 mono_error_init (error);
10133 if (klass->generic_class)
10134 klass = klass->generic_class->container_class;
10136 if (image_is_dynamic (klass->image))
10137 return lookup_custom_attr (klass->image, klass);
10139 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10140 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10141 idx <<= MONO_CUSTOM_ATTR_BITS;
10142 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10144 idx = mono_metadata_token_index (klass->type_token);
10145 idx <<= MONO_CUSTOM_ATTR_BITS;
10146 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10148 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10151 MonoCustomAttrInfo*
10152 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10155 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10156 mono_error_cleanup (&error);
10160 MonoCustomAttrInfo*
10161 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10165 mono_error_init (error);
10167 if (image_is_dynamic (assembly->image))
10168 return lookup_custom_attr (assembly->image, assembly);
10169 idx = 1; /* there is only one assembly */
10170 idx <<= MONO_CUSTOM_ATTR_BITS;
10171 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10172 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10175 static MonoCustomAttrInfo*
10176 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10180 if (image_is_dynamic (image))
10181 return lookup_custom_attr (image, image);
10182 idx = 1; /* there is only one module */
10183 idx <<= MONO_CUSTOM_ATTR_BITS;
10184 idx |= MONO_CUSTOM_ATTR_MODULE;
10185 return mono_custom_attrs_from_index_checked (image, idx, error);
10188 MonoCustomAttrInfo*
10189 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10192 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10193 mono_error_cleanup (&error);
10197 MonoCustomAttrInfo*
10198 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10202 if (image_is_dynamic (klass->image)) {
10203 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10204 return lookup_custom_attr (klass->image, property);
10206 idx = find_property_index (klass, property);
10207 idx <<= MONO_CUSTOM_ATTR_BITS;
10208 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10209 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10212 MonoCustomAttrInfo*
10213 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10216 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10217 mono_error_cleanup (&error);
10221 MonoCustomAttrInfo*
10222 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10226 if (image_is_dynamic (klass->image)) {
10227 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10228 return lookup_custom_attr (klass->image, event);
10230 idx = find_event_index (klass, event);
10231 idx <<= MONO_CUSTOM_ATTR_BITS;
10232 idx |= MONO_CUSTOM_ATTR_EVENT;
10233 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10236 MonoCustomAttrInfo*
10237 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10240 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10241 mono_error_cleanup (&error);
10245 MonoCustomAttrInfo*
10246 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10249 mono_error_init (error);
10251 if (image_is_dynamic (klass->image)) {
10252 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10253 return lookup_custom_attr (klass->image, field);
10255 idx = find_field_index (klass, field);
10256 idx <<= MONO_CUSTOM_ATTR_BITS;
10257 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10258 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10262 * mono_custom_attrs_from_param:
10263 * @method: handle to the method that we want to retrieve custom parameter information from
10264 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10266 * The result must be released with mono_custom_attrs_free().
10268 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10270 MonoCustomAttrInfo*
10271 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10274 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10275 mono_error_cleanup (&error);
10280 * mono_custom_attrs_from_param_checked:
10281 * @method: handle to the method that we want to retrieve custom parameter information from
10282 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10283 * @error: set on error
10285 * The result must be released with mono_custom_attrs_free().
10287 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10289 MonoCustomAttrInfo*
10290 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10293 guint32 i, idx, method_index;
10294 guint32 param_list, param_last, param_pos, found;
10296 MonoReflectionMethodAux *aux;
10298 mono_error_init (error);
10301 * An instantiated method has the same cattrs as the generic method definition.
10303 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10304 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10306 if (method->is_inflated)
10307 method = ((MonoMethodInflated *) method)->declaring;
10309 if (image_is_dynamic (method->klass->image)) {
10310 MonoCustomAttrInfo *res, *ainfo;
10313 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10314 if (!aux || !aux->param_cattr)
10317 /* Need to copy since it will be freed later */
10318 ainfo = aux->param_cattr [param];
10321 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10322 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10323 memcpy (res, ainfo, size);
10327 image = method->klass->image;
10328 method_index = mono_method_get_index (method);
10331 ca = &image->tables [MONO_TABLE_METHOD];
10333 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10334 if (method_index == ca->rows) {
10335 ca = &image->tables [MONO_TABLE_PARAM];
10336 param_last = ca->rows + 1;
10338 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10339 ca = &image->tables [MONO_TABLE_PARAM];
10342 for (i = param_list; i < param_last; ++i) {
10343 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10344 if (param_pos == param) {
10352 idx <<= MONO_CUSTOM_ATTR_BITS;
10353 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10354 return mono_custom_attrs_from_index_checked (image, idx, error);
10358 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10361 for (i = 0; i < ainfo->num_attrs; ++i) {
10362 MonoClass *klass = ainfo->attrs [i].ctor->klass;
10363 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10370 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10373 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10374 mono_error_assert_ok (&error); /*FIXME proper error handling*/
10379 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10384 mono_error_init (error);
10387 for (i = 0; i < ainfo->num_attrs; ++i) {
10388 MonoClass *klass = ainfo->attrs [i].ctor->klass;
10389 if (mono_class_has_parent (klass, attr_klass)) {
10394 if (attr_index == -1)
10397 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10398 if (!mono_error_ok (error))
10400 return mono_array_get (attrs, MonoObject*, attr_index);
10404 * mono_reflection_get_custom_attrs_info:
10405 * @obj: a reflection object handle
10407 * Return the custom attribute info for attributes defined for the
10408 * reflection handle @obj. The objects.
10410 * FIXME this function leaks like a sieve for SRE objects.
10412 MonoCustomAttrInfo*
10413 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10416 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10417 mono_error_assert_ok (&error);
10422 * mono_reflection_get_custom_attrs_info_checked:
10423 * @obj: a reflection object handle
10424 * @error: set on error
10426 * Return the custom attribute info for attributes defined for the
10427 * reflection handle @obj. The objects.
10429 * On failure returns NULL and sets @error.
10431 * FIXME this function leaks like a sieve for SRE objects.
10433 MonoCustomAttrInfo*
10434 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10437 MonoCustomAttrInfo *cinfo = NULL;
10439 mono_error_init (error);
10441 klass = obj->vtable->klass;
10442 if (klass == mono_defaults.runtimetype_class) {
10443 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10444 return_val_if_nok (error, NULL);
10445 klass = mono_class_from_mono_type (type);
10446 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10447 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10448 return_val_if_nok (error, NULL);
10449 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10450 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10451 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10452 return_val_if_nok (error, NULL);
10453 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10454 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10455 cinfo = mono_custom_attrs_from_module (module->image, error);
10456 return_val_if_nok (error, NULL);
10457 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10458 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10459 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10460 return_val_if_nok (error, NULL);
10461 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10462 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10463 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10464 return_val_if_nok (error, NULL);
10465 } else if (strcmp ("MonoField", klass->name) == 0) {
10466 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10467 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10468 return_val_if_nok (error, NULL);
10469 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10470 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10471 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10472 return_val_if_nok (error, NULL);
10473 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10474 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10475 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10476 return_val_if_nok (error, NULL);
10477 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10478 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10479 MonoClass *member_class = mono_object_class (param->MemberImpl);
10480 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10481 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10482 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10483 return_val_if_nok (error, NULL);
10484 } else if (is_sr_mono_property (member_class)) {
10485 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10486 MonoMethod *method;
10487 if (!(method = prop->property->get))
10488 method = prop->property->set;
10491 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10492 return_val_if_nok (error, NULL);
10494 #ifndef DISABLE_REFLECTION_EMIT
10495 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10496 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10497 return_val_if_nok (error, NULL);
10498 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10499 return_val_if_nok (error, NULL);
10500 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10501 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10502 MonoMethod *method = NULL;
10503 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10504 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10505 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10506 method = ((MonoReflectionMethod *)c->cb)->method;
10508 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));
10510 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10511 return_val_if_nok (error, NULL);
10515 char *type_name = mono_type_get_full_name (member_class);
10516 mono_error_set_not_supported (error,
10517 "Custom attributes on a ParamInfo with member %s are not supported",
10519 g_free (type_name);
10522 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10523 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10524 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10525 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10526 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10527 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10528 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10529 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10530 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10531 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10532 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10533 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10534 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10535 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10536 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10537 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10538 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10539 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10540 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10541 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10542 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10543 return_val_if_nok (error, NULL);
10544 } else { /* handle other types here... */
10545 g_error ("get custom attrs not yet supported for %s", klass->name);
10552 * mono_reflection_get_custom_attrs_by_type:
10553 * @obj: a reflection object handle
10555 * Return an array with all the custom attributes defined of the
10556 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10557 * of that type are returned. The objects are fully build. Return NULL if a loading error
10561 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10564 MonoCustomAttrInfo *cinfo;
10566 mono_error_init (error);
10568 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10569 return_val_if_nok (error, NULL);
10571 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10572 if (!cinfo->cached)
10573 mono_custom_attrs_free (cinfo);
10577 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10584 * mono_reflection_get_custom_attrs:
10585 * @obj: a reflection object handle
10587 * Return an array with all the custom attributes defined of the
10588 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10592 mono_reflection_get_custom_attrs (MonoObject *obj)
10596 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10600 * mono_reflection_get_custom_attrs_data:
10601 * @obj: a reflection obj handle
10603 * Returns an array of System.Reflection.CustomAttributeData,
10604 * which include information about attributes reflected on
10605 * types loaded using the Reflection Only methods
10608 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10612 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10613 mono_error_cleanup (&error);
10618 * mono_reflection_get_custom_attrs_data_checked:
10619 * @obj: a reflection obj handle
10620 * @error: set on error
10622 * Returns an array of System.Reflection.CustomAttributeData,
10623 * which include information about attributes reflected on
10624 * types loaded using the Reflection Only methods
10627 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10630 MonoCustomAttrInfo *cinfo;
10632 mono_error_init (error);
10634 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10635 return_val_if_nok (error, NULL);
10637 result = mono_custom_attrs_data_construct (cinfo, error);
10638 if (!cinfo->cached)
10639 mono_custom_attrs_free (cinfo);
10640 return_val_if_nok (error, NULL);
10642 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10647 static MonoReflectionType*
10648 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10650 static MonoMethod *method_get_underlying_system_type = NULL;
10651 MonoReflectionType *rt;
10652 MonoMethod *usertype_method;
10654 mono_error_init (error);
10656 if (!method_get_underlying_system_type)
10657 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10659 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10661 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10668 is_corlib_type (MonoClass *klass)
10670 return klass->image == mono_defaults.corlib;
10673 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10674 static MonoClass *cached_class; \
10675 if (cached_class) \
10676 return cached_class == _class; \
10677 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10678 cached_class = _class; \
10685 #ifndef DISABLE_REFLECTION_EMIT
10687 is_sre_array (MonoClass *klass)
10689 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10693 is_sre_byref (MonoClass *klass)
10695 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10699 is_sre_pointer (MonoClass *klass)
10701 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10705 is_sre_generic_instance (MonoClass *klass)
10707 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10711 is_sre_type_builder (MonoClass *klass)
10713 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10717 is_sre_method_builder (MonoClass *klass)
10719 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10723 is_sre_ctor_builder (MonoClass *klass)
10725 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10729 is_sre_field_builder (MonoClass *klass)
10731 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10735 is_sre_method_on_tb_inst (MonoClass *klass)
10737 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10741 is_sre_ctor_on_tb_inst (MonoClass *klass)
10743 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10747 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10750 mono_error_init (error);
10757 if (is_usertype (ref)) {
10758 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10759 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10765 klass = mono_object_class (ref);
10767 if (is_sre_array (klass)) {
10769 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10770 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10771 return_val_if_nok (error, NULL);
10773 if (sre_array->rank == 0) //single dimentional array
10774 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10776 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10777 sre_array->type.type = res;
10779 } else if (is_sre_byref (klass)) {
10781 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10782 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10783 return_val_if_nok (error, NULL);
10785 res = &mono_class_from_mono_type (base)->this_arg;
10786 sre_byref->type.type = res;
10788 } else if (is_sre_pointer (klass)) {
10790 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10791 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10792 return_val_if_nok (error, NULL);
10794 res = &mono_ptr_class_get (base)->byval_arg;
10795 sre_pointer->type.type = res;
10797 } else if (is_sre_generic_instance (klass)) {
10798 MonoType *res, **types;
10799 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10802 count = mono_array_length (gclass->type_arguments);
10803 types = g_new0 (MonoType*, count);
10804 for (i = 0; i < count; ++i) {
10805 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10806 types [i] = mono_reflection_type_get_handle (t, error);
10807 if (!types[i] || !is_ok (error)) {
10813 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10816 gclass->type.type = res;
10820 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10825 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10828 mono_reflection_type_get_handle (type, &error);
10829 mono_error_set_pending_exception (&error);
10833 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10835 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10838 mono_error_init (error);
10840 MonoType *res = mono_reflection_type_get_handle (type, error);
10842 if (!res && is_ok (error)) {
10843 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10845 return_val_if_nok (error, FALSE);
10847 klass = mono_class_from_mono_type (res);
10849 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10850 mono_domain_lock (domain);
10852 if (!image_is_dynamic (klass->image)) {
10853 mono_class_setup_supertypes (klass);
10855 if (!domain->type_hash)
10856 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10857 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10858 mono_g_hash_table_insert (domain->type_hash, res, type);
10860 mono_domain_unlock (domain);
10861 mono_loader_unlock ();
10867 mono_reflection_register_with_runtime (MonoReflectionType *type)
10870 (void) reflection_register_with_runtime (type, &error);
10871 mono_error_set_pending_exception (&error);
10875 * LOCKING: Assumes the loader lock is held.
10877 static MonoMethodSignature*
10878 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10879 MonoMethodSignature *sig;
10882 mono_error_init (error);
10884 count = parameters? mono_array_length (parameters): 0;
10886 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10887 sig->param_count = count;
10888 sig->sentinelpos = -1; /* FIXME */
10889 for (i = 0; i < count; ++i) {
10890 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10891 if (!is_ok (error)) {
10892 image_g_free (image, sig);
10900 * LOCKING: Assumes the loader lock is held.
10902 static MonoMethodSignature*
10903 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10904 MonoMethodSignature *sig;
10906 mono_error_init (error);
10908 sig = parameters_to_signature (image, ctor->parameters, error);
10909 return_val_if_nok (error, NULL);
10910 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10911 sig->ret = &mono_defaults.void_class->byval_arg;
10916 * LOCKING: Assumes the loader lock is held.
10918 static MonoMethodSignature*
10919 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10920 MonoMethodSignature *sig;
10922 mono_error_init (error);
10924 sig = parameters_to_signature (image, method->parameters, error);
10925 return_val_if_nok (error, NULL);
10926 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10927 if (method->rtype) {
10928 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10929 if (!is_ok (error)) {
10930 image_g_free (image, sig);
10934 sig->ret = &mono_defaults.void_class->byval_arg;
10936 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10940 static MonoMethodSignature*
10941 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10942 MonoMethodSignature *sig;
10944 mono_error_init (error);
10946 sig = parameters_to_signature (NULL, method->parameters, error);
10947 return_val_if_nok (error, NULL);
10948 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10949 if (method->rtype) {
10950 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10951 if (!is_ok (error)) {
10956 sig->ret = &mono_defaults.void_class->byval_arg;
10958 sig->generic_param_count = 0;
10963 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10965 mono_error_init (error);
10966 MonoClass *klass = mono_object_class (prop);
10967 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10968 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10969 *name = mono_string_to_utf8_checked (pb->name, error);
10970 return_if_nok (error);
10971 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10973 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10974 *name = g_strdup (p->property->name);
10975 if (p->property->get)
10976 *type = mono_method_signature (p->property->get)->ret;
10978 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10983 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10985 mono_error_init (error);
10986 MonoClass *klass = mono_object_class (field);
10987 if (strcmp (klass->name, "FieldBuilder") == 0) {
10988 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10989 *name = mono_string_to_utf8_checked (fb->name, error);
10990 return_if_nok (error);
10991 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10993 MonoReflectionField *f = (MonoReflectionField *)field;
10994 *name = g_strdup (mono_field_get_name (f->field));
10995 *type = f->field->type;
10999 #else /* DISABLE_REFLECTION_EMIT */
11002 mono_reflection_register_with_runtime (MonoReflectionType *type)
11004 /* This is empty */
11008 is_sre_type_builder (MonoClass *klass)
11014 is_sre_generic_instance (MonoClass *klass)
11020 init_type_builder_generics (MonoObject *type, MonoError *error)
11022 mono_error_init (error);
11025 #endif /* !DISABLE_REFLECTION_EMIT */
11029 is_sr_mono_field (MonoClass *klass)
11031 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
11035 is_sr_mono_property (MonoClass *klass)
11037 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
11041 is_sr_mono_method (MonoClass *klass)
11043 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
11047 is_sr_mono_cmethod (MonoClass *klass)
11049 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
11053 is_sr_mono_generic_method (MonoClass *klass)
11055 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11059 is_sr_mono_generic_cmethod (MonoClass *klass)
11061 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11065 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11067 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11071 is_usertype (MonoReflectionType *ref)
11073 MonoClass *klass = mono_object_class (ref);
11074 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11077 static MonoReflectionType*
11078 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11080 mono_error_init (error);
11081 if (!type || type->type)
11084 if (is_usertype (type)) {
11085 type = mono_reflection_type_get_underlying_system_type (type, error);
11086 return_val_if_nok (error, NULL);
11087 if (is_usertype (type)) {
11088 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11096 * encode_cattr_value:
11097 * Encode a value in a custom attribute stream of bytes.
11098 * The value to encode is either supplied as an object in argument val
11099 * (valuetypes are boxed), or as a pointer to the data in the
11101 * @type represents the type of the value
11102 * @buffer is the start of the buffer
11103 * @p the current position in the buffer
11104 * @buflen contains the size of the buffer and is used to return the new buffer size
11105 * if this needs to be realloced.
11106 * @retbuffer and @retp return the start and the position of the buffer
11107 * @error set on error.
11110 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11112 MonoTypeEnum simple_type;
11114 mono_error_init (error);
11115 if ((p-buffer) + 10 >= *buflen) {
11118 newbuf = (char *)g_realloc (buffer, *buflen);
11119 p = newbuf + (p-buffer);
11123 argval = ((char*)arg + sizeof (MonoObject));
11124 simple_type = type->type;
11126 switch (simple_type) {
11127 case MONO_TYPE_BOOLEAN:
11132 case MONO_TYPE_CHAR:
11135 swap_with_size (p, argval, 2, 1);
11141 swap_with_size (p, argval, 4, 1);
11145 swap_with_size (p, argval, 8, 1);
11150 swap_with_size (p, argval, 8, 1);
11153 case MONO_TYPE_VALUETYPE:
11154 if (type->data.klass->enumtype) {
11155 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11158 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11161 case MONO_TYPE_STRING: {
11168 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11169 return_if_nok (error);
11170 slen = strlen (str);
11171 if ((p-buffer) + 10 + slen >= *buflen) {
11175 newbuf = (char *)g_realloc (buffer, *buflen);
11176 p = newbuf + (p-buffer);
11179 mono_metadata_encode_value (slen, p, &p);
11180 memcpy (p, str, slen);
11185 case MONO_TYPE_CLASS: {
11188 MonoType *arg_type;
11194 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11195 return_if_nok (error);
11197 str = type_get_qualified_name (arg_type, NULL);
11198 slen = strlen (str);
11199 if ((p-buffer) + 10 + slen >= *buflen) {
11203 newbuf = (char *)g_realloc (buffer, *buflen);
11204 p = newbuf + (p-buffer);
11207 mono_metadata_encode_value (slen, p, &p);
11208 memcpy (p, str, slen);
11213 case MONO_TYPE_SZARRAY: {
11215 MonoClass *eclass, *arg_eclass;
11218 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11221 len = mono_array_length ((MonoArray*)arg);
11223 *p++ = (len >> 8) & 0xff;
11224 *p++ = (len >> 16) & 0xff;
11225 *p++ = (len >> 24) & 0xff;
11227 *retbuffer = buffer;
11228 eclass = type->data.klass;
11229 arg_eclass = mono_object_class (arg)->element_class;
11232 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11233 eclass = mono_defaults.object_class;
11235 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11236 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11237 int elsize = mono_class_array_element_size (arg_eclass);
11238 for (i = 0; i < len; ++i) {
11239 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11240 return_if_nok (error);
11243 } else if (eclass->valuetype && arg_eclass->valuetype) {
11244 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11245 int elsize = mono_class_array_element_size (eclass);
11246 for (i = 0; i < len; ++i) {
11247 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11248 return_if_nok (error);
11252 for (i = 0; i < len; ++i) {
11253 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11254 return_if_nok (error);
11259 case MONO_TYPE_OBJECT: {
11265 * The parameter type is 'object' but the type of the actual
11266 * argument is not. So we have to add type information to the blob
11267 * too. This is completely undocumented in the spec.
11271 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11276 klass = mono_object_class (arg);
11278 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11282 return_if_nok (error);
11285 if (klass->enumtype) {
11287 } else if (klass == mono_defaults.string_class) {
11288 simple_type = MONO_TYPE_STRING;
11291 } else if (klass->rank == 1) {
11293 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11294 /* See Partition II, Appendix B3 */
11297 *p++ = klass->element_class->byval_arg.type;
11298 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11299 return_if_nok (error);
11301 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11302 *p++ = simple_type = klass->byval_arg.type;
11305 g_error ("unhandled type in custom attr");
11307 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11308 slen = strlen (str);
11309 if ((p-buffer) + 10 + slen >= *buflen) {
11313 newbuf = (char *)g_realloc (buffer, *buflen);
11314 p = newbuf + (p-buffer);
11317 mono_metadata_encode_value (slen, p, &p);
11318 memcpy (p, str, slen);
11321 simple_type = mono_class_enum_basetype (klass)->type;
11325 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11328 *retbuffer = buffer;
11332 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11334 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11335 char *str = type_get_qualified_name (type, NULL);
11336 int slen = strlen (str);
11340 * This seems to be optional...
11343 mono_metadata_encode_value (slen, p, &p);
11344 memcpy (p, str, slen);
11347 } else if (type->type == MONO_TYPE_OBJECT) {
11349 } else if (type->type == MONO_TYPE_CLASS) {
11350 /* it should be a type: encode_cattr_value () has the check */
11353 mono_metadata_encode_value (type->type, p, &p);
11354 if (type->type == MONO_TYPE_SZARRAY)
11355 /* See the examples in Partition VI, Annex B */
11356 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11362 #ifndef DISABLE_REFLECTION_EMIT
11364 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11368 mono_error_init (error);
11370 /* Preallocate a large enough buffer */
11371 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11372 char *str = type_get_qualified_name (type, NULL);
11373 len = strlen (str);
11375 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11376 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11377 len = strlen (str);
11382 len += strlen (name);
11384 if ((p-buffer) + 20 + len >= *buflen) {
11388 newbuf = (char *)g_realloc (buffer, *buflen);
11389 p = newbuf + (p-buffer);
11393 encode_field_or_prop_type (type, p, &p);
11395 len = strlen (name);
11396 mono_metadata_encode_value (len, p, &p);
11397 memcpy (p, name, len);
11399 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11400 return_if_nok (error);
11402 *retbuffer = buffer;
11406 * mono_reflection_get_custom_attrs_blob:
11407 * @ctor: custom attribute constructor
11408 * @ctorArgs: arguments o the constructor
11414 * Creates the blob of data that needs to be saved in the metadata and that represents
11415 * the custom attributed described by @ctor, @ctorArgs etc.
11416 * Returns: a Byte array representing the blob of data.
11419 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11422 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11423 mono_error_cleanup (&error);
11428 * mono_reflection_get_custom_attrs_blob_checked:
11429 * @ctor: custom attribute constructor
11430 * @ctorArgs: arguments o the constructor
11435 * @error: set on error
11437 * Creates the blob of data that needs to be saved in the metadata and that represents
11438 * the custom attributed described by @ctor, @ctorArgs etc.
11439 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11442 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11444 MonoArray *result = NULL;
11445 MonoMethodSignature *sig;
11450 mono_error_init (error);
11452 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11453 /* sig is freed later so allocate it in the heap */
11454 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11455 if (!is_ok (error)) {
11460 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11463 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11465 p = buffer = (char *)g_malloc (buflen);
11466 /* write the prolog */
11469 for (i = 0; i < sig->param_count; ++i) {
11470 arg = mono_array_get (ctorArgs, MonoObject*, i);
11471 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11472 if (!is_ok (error)) goto leave;
11476 i += mono_array_length (properties);
11478 i += mono_array_length (fields);
11480 *p++ = (i >> 8) & 0xff;
11483 for (i = 0; i < mono_array_length (properties); ++i) {
11487 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11488 get_prop_name_and_type (prop, &pname, &ptype, error);
11489 if (!is_ok (error)) goto leave;
11490 *p++ = 0x54; /* PROPERTY signature */
11491 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11493 if (!is_ok (error)) goto leave;
11499 for (i = 0; i < mono_array_length (fields); ++i) {
11503 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11504 get_field_name_and_type (field, &fname, &ftype, error);
11505 if (!is_ok (error)) goto leave;
11506 *p++ = 0x53; /* FIELD signature */
11507 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11509 if (!is_ok (error)) goto leave;
11513 g_assert (p - buffer <= buflen);
11514 buflen = p - buffer;
11515 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11516 if (!is_ok (error))
11518 p = mono_array_addr (result, char, 0);
11519 memcpy (p, buffer, buflen);
11522 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11528 * reflection_setup_internal_class:
11529 * @tb: a TypeBuilder object
11530 * @error: set on error
11532 * Creates a MonoClass that represents the TypeBuilder.
11533 * This is a trick that lets us simplify a lot of reflection code
11534 * (and will allow us to support Build and Run assemblies easier).
11536 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11539 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11541 MonoClass *klass, *parent;
11543 mono_error_init (error);
11544 RESOLVE_TYPE (tb->parent, error);
11545 return_val_if_nok (error, FALSE);
11547 mono_loader_lock ();
11550 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11551 if (!is_ok (error)) {
11552 mono_loader_unlock ();
11555 /* check so we can compile corlib correctly */
11556 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11557 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11558 parent = parent_type->data.klass;
11560 parent = mono_class_from_mono_type (parent_type);
11566 /* the type has already being created: it means we just have to change the parent */
11567 if (tb->type.type) {
11568 klass = mono_class_from_mono_type (tb->type.type);
11569 klass->parent = NULL;
11570 /* fool mono_class_setup_parent */
11571 klass->supertypes = NULL;
11572 mono_class_setup_parent (klass, parent);
11573 mono_class_setup_mono_type (klass);
11574 mono_loader_unlock ();
11578 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11580 klass->image = &tb->module->dynamic_image->image;
11582 klass->inited = 1; /* we lie to the runtime */
11583 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11584 if (!is_ok (error))
11586 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11587 if (!is_ok (error))
11589 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11590 klass->flags = tb->attrs;
11592 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11594 klass->element_class = klass;
11596 if (mono_class_get_ref_info (klass) == NULL) {
11598 mono_class_set_ref_info (klass, tb);
11600 /* Put into cache so mono_class_get_checked () will find it.
11601 Skip nested types as those should not be available on the global scope. */
11602 if (!tb->nesting_type)
11603 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11606 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11607 by performing a mono_class_get which does the full resolution.
11609 Working around this semantics would require us to write a lot of code for no clear advantage.
11611 mono_image_append_class_to_reflection_info_set (klass);
11613 g_assert (mono_class_get_ref_info (klass) == tb);
11616 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11618 if (parent != NULL) {
11619 mono_class_setup_parent (klass, parent);
11620 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11621 const char *old_n = klass->name;
11622 /* trick to get relative numbering right when compiling corlib */
11623 klass->name = "BuildingObject";
11624 mono_class_setup_parent (klass, mono_defaults.object_class);
11625 klass->name = old_n;
11628 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11629 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11630 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11631 klass->instance_size = sizeof (MonoObject);
11632 klass->size_inited = 1;
11633 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11636 mono_class_setup_mono_type (klass);
11638 mono_class_setup_supertypes (klass);
11641 * FIXME: handle interfaces.
11644 tb->type.type = &klass->byval_arg;
11646 if (tb->nesting_type) {
11647 g_assert (tb->nesting_type->type);
11648 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11649 if (!is_ok (error)) goto failure;
11650 klass->nested_in = mono_class_from_mono_type (nesting_type);
11653 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11655 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11657 mono_loader_unlock ();
11661 mono_loader_unlock ();
11666 * mono_reflection_setup_internal_class:
11667 * @tb: a TypeBuilder object
11670 * Creates a MonoClass that represents the TypeBuilder.
11671 * This is a trick that lets us simplify a lot of reflection code
11672 * (and will allow us to support Build and Run assemblies easier).
11676 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11679 (void) reflection_setup_internal_class (tb, &error);
11680 mono_error_set_pending_exception (&error);
11684 * mono_reflection_setup_generic_class:
11685 * @tb: a TypeBuilder object
11687 * Setup the generic class before adding the first generic parameter.
11690 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11695 * mono_reflection_create_generic_class:
11696 * @tb: a TypeBuilder object
11697 * @error: set on error
11699 * Creates the generic class after all generic parameters have been added.
11700 * On success returns TRUE, on failure returns FALSE and sets @error.
11704 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11710 mono_error_init (error);
11712 klass = mono_class_from_mono_type (tb->type.type);
11714 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11716 if (klass->generic_container || (count == 0))
11719 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11721 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11723 klass->generic_container->owner.klass = klass;
11724 klass->generic_container->type_argc = count;
11725 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11727 klass->is_generic = 1;
11729 for (i = 0; i < count; i++) {
11730 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11731 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11732 return_val_if_nok (error, FALSE);
11733 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11734 klass->generic_container->type_params [i] = *param;
11735 /*Make sure we are a diferent type instance */
11736 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11737 klass->generic_container->type_params [i].info.pklass = NULL;
11738 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11740 g_assert (klass->generic_container->type_params [i].param.owner);
11743 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11748 * reflection_create_internal_class:
11749 * @tb: a TypeBuilder object
11750 * @error: set on error
11752 * Actually create the MonoClass that is associated with the TypeBuilder.
11753 * On success returns TRUE, on failure returns FALSE and sets @error.
11757 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11762 mono_error_init (error);
11763 klass = mono_class_from_mono_type (tb->type.type);
11765 mono_loader_lock ();
11766 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11767 MonoReflectionFieldBuilder *fb;
11769 MonoType *enum_basetype;
11771 g_assert (tb->fields != NULL);
11772 g_assert (mono_array_length (tb->fields) >= 1);
11774 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11776 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11777 if (!is_ok (error)) {
11778 mono_loader_unlock ();
11781 if (!mono_type_is_valid_enum_basetype (field_type)) {
11782 mono_loader_unlock ();
11786 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11787 if (!is_ok (error)) {
11788 mono_loader_unlock ();
11791 klass->element_class = mono_class_from_mono_type (enum_basetype);
11792 if (!klass->element_class)
11793 klass->element_class = mono_class_from_mono_type (enum_basetype);
11796 * get the element_class from the current corlib.
11798 ec = default_class_from_mono_type (enum_basetype);
11799 klass->instance_size = ec->instance_size;
11800 klass->size_inited = 1;
11802 * this is almost safe to do with enums and it's needed to be able
11803 * to create objects of the enum type (for use in SetConstant).
11805 /* FIXME: Does this mean enums can't have method overrides ? */
11806 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11808 mono_loader_unlock ();
11813 * mono_reflection_create_internal_class:
11814 * @tb: a TypeBuilder object
11817 * Actually create the MonoClass that is associated with the TypeBuilder.
11820 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11823 (void) reflection_create_internal_class (tb, &error);
11824 mono_error_set_pending_exception (&error);
11827 static MonoMarshalSpec*
11828 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11829 MonoReflectionMarshal *minfo, MonoError *error)
11831 MonoMarshalSpec *res;
11833 mono_error_init (error);
11835 res = image_g_new0 (image, MonoMarshalSpec, 1);
11836 res->native = (MonoMarshalNative)minfo->type;
11838 switch (minfo->type) {
11839 case MONO_NATIVE_LPARRAY:
11840 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11841 if (minfo->has_size) {
11842 res->data.array_data.param_num = minfo->param_num;
11843 res->data.array_data.num_elem = minfo->count;
11844 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11847 res->data.array_data.param_num = -1;
11848 res->data.array_data.num_elem = -1;
11849 res->data.array_data.elem_mult = -1;
11853 case MONO_NATIVE_BYVALTSTR:
11854 case MONO_NATIVE_BYVALARRAY:
11855 res->data.array_data.num_elem = minfo->count;
11858 case MONO_NATIVE_CUSTOM:
11859 if (minfo->marshaltyperef) {
11860 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11861 if (!is_ok (error)) {
11862 image_g_free (image, res);
11865 res->data.custom_data.custom_name =
11866 type_get_fully_qualified_name (marshaltyperef);
11868 if (minfo->mcookie) {
11869 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11870 if (!is_ok (error)) {
11871 image_g_free (image, res);
11883 #endif /* !DISABLE_REFLECTION_EMIT */
11885 MonoReflectionMarshalAsAttribute*
11886 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11887 MonoMarshalSpec *spec, MonoError *error)
11889 MonoReflectionType *rt;
11890 MonoReflectionMarshalAsAttribute *minfo;
11893 mono_error_init (error);
11895 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11898 minfo->utype = spec->native;
11900 switch (minfo->utype) {
11901 case MONO_NATIVE_LPARRAY:
11902 minfo->array_subtype = spec->data.array_data.elem_type;
11903 minfo->size_const = spec->data.array_data.num_elem;
11904 if (spec->data.array_data.param_num != -1)
11905 minfo->size_param_index = spec->data.array_data.param_num;
11908 case MONO_NATIVE_BYVALTSTR:
11909 case MONO_NATIVE_BYVALARRAY:
11910 minfo->size_const = spec->data.array_data.num_elem;
11913 case MONO_NATIVE_CUSTOM:
11914 if (spec->data.custom_data.custom_name) {
11915 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11916 return_val_if_nok (error, NULL);
11919 rt = mono_type_get_object_checked (domain, mtype, error);
11923 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11926 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11928 if (spec->data.custom_data.cookie)
11929 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11939 #ifndef DISABLE_REFLECTION_EMIT
11941 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11942 ReflectionMethodBuilder *rmb,
11943 MonoMethodSignature *sig,
11947 MonoMethodWrapper *wrapperm;
11948 MonoMarshalSpec **specs;
11949 MonoReflectionMethodAux *method_aux;
11954 mono_error_init (error);
11956 * Methods created using a MethodBuilder should have their memory allocated
11957 * inside the image mempool, while dynamic methods should have their memory
11960 dynamic = rmb->refs != NULL;
11961 image = dynamic ? NULL : klass->image;
11964 g_assert (!klass->generic_class);
11966 mono_loader_lock ();
11968 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11969 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11970 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11972 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11974 wrapperm = (MonoMethodWrapper*)m;
11976 m->dynamic = dynamic;
11978 m->flags = rmb->attrs;
11979 m->iflags = rmb->iattrs;
11980 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11982 m->signature = sig;
11983 m->sre_method = TRUE;
11984 m->skip_visibility = rmb->skip_visibility;
11985 if (rmb->table_idx)
11986 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11988 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11989 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11990 m->string_ctor = 1;
11992 m->signature->pinvoke = 1;
11993 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11994 m->signature->pinvoke = 1;
11996 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11998 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11999 mono_error_assert_ok (error);
12000 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
12001 mono_error_assert_ok (error);
12003 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
12005 if (image_is_dynamic (klass->image))
12006 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12008 mono_loader_unlock ();
12011 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
12012 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
12013 MonoMethodHeader *header;
12015 gint32 max_stack, i;
12016 gint32 num_locals = 0;
12017 gint32 num_clauses = 0;
12021 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
12022 code_size = rmb->ilgen->code_len;
12023 max_stack = rmb->ilgen->max_stack;
12024 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
12025 if (rmb->ilgen->ex_handlers)
12026 num_clauses = method_count_clauses (rmb->ilgen);
12029 code = mono_array_addr (rmb->code, guint8, 0);
12030 code_size = mono_array_length (rmb->code);
12031 /* we probably need to run a verifier on the code... */
12041 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
12042 header->code_size = code_size;
12043 header->code = (const unsigned char *)image_g_malloc (image, code_size);
12044 memcpy ((char*)header->code, code, code_size);
12045 header->max_stack = max_stack;
12046 header->init_locals = rmb->init_locals;
12047 header->num_locals = num_locals;
12049 for (i = 0; i < num_locals; ++i) {
12050 MonoReflectionLocalBuilder *lb =
12051 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
12053 header->locals [i] = image_g_new0 (image, MonoType, 1);
12054 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12055 mono_error_assert_ok (error);
12056 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12059 header->num_clauses = num_clauses;
12061 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12062 rmb->ilgen, num_clauses, error);
12063 mono_error_assert_ok (error);
12066 wrapperm->header = header;
12069 if (rmb->generic_params) {
12070 int count = mono_array_length (rmb->generic_params);
12071 MonoGenericContainer *container = rmb->generic_container;
12073 g_assert (container);
12075 container->type_argc = count;
12076 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12077 container->owner.method = m;
12078 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12080 m->is_generic = TRUE;
12081 mono_method_set_generic_container (m, container);
12083 for (i = 0; i < count; i++) {
12084 MonoReflectionGenericParam *gp =
12085 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12086 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12087 mono_error_assert_ok (error);
12088 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12089 container->type_params [i] = *param;
12093 * The method signature might have pointers to generic parameters that belong to other methods.
12094 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12095 * generic parameters.
12097 for (i = 0; i < m->signature->param_count; ++i) {
12098 MonoType *t = m->signature->params [i];
12099 if (t->type == MONO_TYPE_MVAR) {
12100 MonoGenericParam *gparam = t->data.generic_param;
12101 if (gparam->num < count) {
12102 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12103 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12109 if (klass->generic_container) {
12110 container->parent = klass->generic_container;
12111 container->context.class_inst = klass->generic_container->context.class_inst;
12113 container->context.method_inst = mono_get_shared_generic_inst (container);
12117 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12121 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12123 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12124 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12125 for (i = 0; i < rmb->nrefs; ++i)
12126 data [i + 1] = rmb->refs [i];
12131 /* Parameter info */
12134 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12135 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12136 for (i = 0; i <= m->signature->param_count; ++i) {
12137 MonoReflectionParamBuilder *pb;
12138 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12139 if ((i > 0) && (pb->attrs)) {
12140 /* Make a copy since it might point to a shared type structure */
12141 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12142 m->signature->params [i - 1]->attrs = pb->attrs;
12145 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12146 MonoDynamicImage *assembly;
12148 MonoTypeEnum def_type;
12152 if (!method_aux->param_defaults) {
12153 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12154 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12156 assembly = (MonoDynamicImage*)klass->image;
12157 idx = encode_constant (assembly, pb->def_value, &def_type);
12158 /* Copy the data from the blob since it might get realloc-ed */
12159 p = assembly->blob.data + idx;
12160 len = mono_metadata_decode_blob_size (p, &p2);
12162 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12163 method_aux->param_default_types [i] = def_type;
12164 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12168 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12169 mono_error_assert_ok (error);
12172 if (!method_aux->param_cattr)
12173 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12174 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12180 /* Parameter marshalling */
12183 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12184 MonoReflectionParamBuilder *pb;
12185 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12186 if (pb->marshal_info) {
12188 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12189 specs [pb->position] =
12190 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12191 if (!is_ok (error)) {
12192 mono_loader_unlock ();
12193 image_g_free (image, specs);
12194 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12200 if (specs != NULL) {
12202 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12203 method_aux->param_marshall = specs;
12206 if (image_is_dynamic (klass->image) && method_aux)
12207 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12209 mono_loader_unlock ();
12215 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12217 ReflectionMethodBuilder rmb;
12218 MonoMethodSignature *sig;
12220 mono_loader_lock ();
12221 g_assert (klass->image != NULL);
12222 sig = ctor_builder_to_signature (klass->image, mb, error);
12223 mono_loader_unlock ();
12224 return_val_if_nok (error, NULL);
12226 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12229 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12230 return_val_if_nok (error, NULL);
12231 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12233 /* If we are in a generic class, we might be called multiple times from inflate_method */
12234 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12235 /* ilgen is no longer needed */
12239 return mb->mhandle;
12243 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12245 ReflectionMethodBuilder rmb;
12246 MonoMethodSignature *sig;
12248 mono_error_init (error);
12250 mono_loader_lock ();
12251 g_assert (klass->image != NULL);
12252 sig = method_builder_to_signature (klass->image, mb, error);
12253 mono_loader_unlock ();
12254 return_val_if_nok (error, NULL);
12256 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12259 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12260 return_val_if_nok (error, NULL);
12261 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12263 /* If we are in a generic class, we might be called multiple times from inflate_method */
12264 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12265 /* ilgen is no longer needed */
12268 return mb->mhandle;
12271 static MonoClassField*
12272 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12274 MonoClassField *field;
12277 mono_error_init (error);
12279 field = g_new0 (MonoClassField, 1);
12281 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12282 mono_error_assert_ok (error);
12283 if (fb->attrs || fb->modreq || fb->modopt) {
12284 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12285 if (!is_ok (error)) {
12289 field->type = mono_metadata_type_dup (NULL, type);
12290 field->type->attrs = fb->attrs;
12292 g_assert (image_is_dynamic (klass->image));
12293 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12294 g_free (field->type);
12295 if (!is_ok (error)) {
12299 field->type = mono_metadata_type_dup (klass->image, custom);
12302 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12303 if (!is_ok (error)) {
12308 if (fb->offset != -1)
12309 field->offset = fb->offset;
12310 field->parent = klass;
12311 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12313 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12320 * mono_reflection_bind_generic_parameters:
12321 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12322 * @type_args: the number of type arguments to bind
12323 * @types: array of type arguments
12324 * @error: set on error
12326 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12327 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12330 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12333 MonoReflectionTypeBuilder *tb = NULL;
12334 gboolean is_dynamic = FALSE;
12335 MonoClass *geninst;
12337 mono_error_init (error);
12339 mono_loader_lock ();
12341 if (is_sre_type_builder (mono_object_class (type))) {
12342 tb = (MonoReflectionTypeBuilder *) type;
12345 } else if (is_sre_generic_instance (mono_object_class (type))) {
12346 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12347 MonoReflectionType *gtd = rgi->generic_type;
12349 if (is_sre_type_builder (mono_object_class (gtd))) {
12350 tb = (MonoReflectionTypeBuilder *)gtd;
12355 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12356 if (tb && tb->generic_container) {
12357 if (!mono_reflection_create_generic_class (tb, error)) {
12358 mono_loader_unlock ();
12363 MonoType *t = mono_reflection_type_get_handle (type, error);
12364 if (!is_ok (error)) {
12365 mono_loader_unlock ();
12369 klass = mono_class_from_mono_type (t);
12370 if (!klass->generic_container) {
12371 mono_loader_unlock ();
12372 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12376 if (klass->wastypebuilder) {
12377 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12382 mono_loader_unlock ();
12384 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12386 return &geninst->byval_arg;
12390 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12392 MonoGenericClass *gclass;
12393 MonoGenericInst *inst;
12395 g_assert (klass->generic_container);
12397 inst = mono_metadata_get_generic_inst (type_argc, types);
12398 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12400 return mono_generic_class_get_class (gclass);
12403 static MonoReflectionMethod*
12404 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12407 MonoMethod *method, *inflated;
12408 MonoMethodInflated *imethod;
12409 MonoGenericContext tmp_context;
12410 MonoGenericInst *ginst;
12411 MonoType **type_argv;
12414 mono_error_init (error);
12416 /*FIXME but this no longer should happen*/
12417 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12418 #ifndef DISABLE_REFLECTION_EMIT
12419 MonoReflectionMethodBuilder *mb = NULL;
12423 mb = (MonoReflectionMethodBuilder *) rmethod;
12424 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12425 return_val_if_nok (error, NULL);
12426 klass = mono_class_from_mono_type (tb);
12428 method = methodbuilder_to_mono_method (klass, mb, error);
12429 return_val_if_nok (error, NULL);
12431 g_assert_not_reached ();
12435 method = rmethod->method;
12438 klass = method->klass;
12440 if (method->is_inflated)
12441 method = ((MonoMethodInflated *) method)->declaring;
12443 count = mono_method_signature (method)->generic_param_count;
12444 if (count != mono_array_length (types))
12447 type_argv = g_new0 (MonoType *, count);
12448 for (i = 0; i < count; i++) {
12449 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12450 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12451 if (!is_ok (error)) {
12452 g_free (type_argv);
12456 ginst = mono_metadata_get_generic_inst (count, type_argv);
12457 g_free (type_argv);
12459 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12460 tmp_context.method_inst = ginst;
12462 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12463 mono_error_assert_ok (error);
12464 imethod = (MonoMethodInflated *) inflated;
12466 /*FIXME but I think this is no longer necessary*/
12467 if (image_is_dynamic (method->klass->image)) {
12468 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12470 * This table maps metadata structures representing inflated methods/fields
12471 * to the reflection objects representing their generic definitions.
12473 mono_image_lock ((MonoImage*)image);
12474 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12475 mono_image_unlock ((MonoImage*)image);
12478 if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12479 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12483 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12487 MonoReflectionMethod*
12488 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12491 MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12492 mono_error_set_pending_exception (&error);
12497 #ifndef DISABLE_REFLECTION_EMIT
12499 static MonoMethod *
12500 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12502 MonoMethodInflated *imethod;
12503 MonoGenericContext *context;
12507 * With generic code sharing the klass might not be inflated.
12508 * This can happen because classes inflated with their own
12509 * type arguments are "normalized" to the uninflated class.
12511 if (!klass->generic_class)
12514 context = mono_class_get_context (klass);
12516 if (klass->method.count && klass->methods) {
12517 /* Find the already created inflated method */
12518 for (i = 0; i < klass->method.count; ++i) {
12519 g_assert (klass->methods [i]->is_inflated);
12520 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12523 g_assert (i < klass->method.count);
12524 imethod = (MonoMethodInflated*)klass->methods [i];
12527 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12528 mono_error_assert_ok (&error);
12531 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12532 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12534 mono_image_lock ((MonoImage*)image);
12535 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12536 mono_image_unlock ((MonoImage*)image);
12538 return (MonoMethod *) imethod;
12541 static MonoMethod *
12542 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12544 MonoMethod *method;
12547 mono_error_init (error);
12549 MonoClass *type_class = mono_object_class (type);
12551 if (is_sre_generic_instance (type_class)) {
12552 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12553 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12554 return_val_if_nok (error, NULL);
12555 gklass = mono_class_from_mono_type (generic_type);
12556 } else if (is_sre_type_builder (type_class)) {
12557 MonoType *t = mono_reflection_type_get_handle (type, error);
12558 return_val_if_nok (error, NULL);
12559 gklass = mono_class_from_mono_type (t);
12560 } else if (type->type) {
12561 gklass = mono_class_from_mono_type (type->type);
12562 gklass = mono_class_get_generic_type_definition (gklass);
12564 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12567 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12568 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12569 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12571 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12575 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12576 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12579 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12580 method = ((MonoReflectionMethod *) obj)->method;
12582 method = NULL; /* prevent compiler warning */
12583 g_error ("can't handle type %s", obj->vtable->klass->name);
12586 MonoType *t = mono_reflection_type_get_handle (type, error);
12587 return_val_if_nok (error, NULL);
12588 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12591 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12593 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12595 MonoGenericClass *gclass;
12596 MonoDynamicGenericClass *dgclass;
12597 MonoClass *klass, *gklass;
12601 mono_error_init (error);
12603 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12604 return_val_if_nok (error, FALSE);
12605 klass = mono_class_from_mono_type (gtype);
12606 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12607 gclass = gtype->data.generic_class;
12609 if (!gclass->is_dynamic)
12612 dgclass = (MonoDynamicGenericClass *) gclass;
12614 if (dgclass->initialized)
12617 gklass = gclass->container_class;
12618 mono_class_init (gklass);
12620 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12622 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12623 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12624 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12626 for (i = 0; i < dgclass->count_fields; i++) {
12627 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12628 MonoClassField *field, *inflated_field = NULL;
12630 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12631 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12632 return_val_if_nok (error, FALSE);
12633 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12634 field = ((MonoReflectionField *) obj)->field;
12636 field = NULL; /* prevent compiler warning */
12637 g_assert_not_reached ();
12640 dgclass->fields [i] = *field;
12641 dgclass->fields [i].parent = klass;
12642 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12643 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12644 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12645 dgclass->field_generic_types [i] = field->type;
12646 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12647 dgclass->field_objects [i] = obj;
12649 if (inflated_field) {
12650 g_free (inflated_field);
12652 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12656 dgclass->initialized = TRUE;
12661 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12664 (void) reflection_generic_class_initialize (type, fields, &error);
12665 mono_error_set_pending_exception (&error);
12669 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12671 MonoDynamicGenericClass *dgclass;
12674 g_assert (gclass->is_dynamic);
12676 dgclass = (MonoDynamicGenericClass *)gclass;
12678 for (i = 0; i < dgclass->count_fields; ++i) {
12679 MonoClassField *field = dgclass->fields + i;
12680 mono_metadata_free_type (field->type);
12681 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12686 * fix_partial_generic_class:
12687 * @klass: a generic instantiation MonoClass
12688 * @error: set on error
12690 * Assumes that the generic container of @klass has its vtable
12691 * initialized, and updates the parent class, insterfaces, methods and
12692 * fields of @klass by inflating the types using the generic context.
12694 * On success returns TRUE, on failure returns FALSE and sets @error.
12698 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12700 MonoClass *gklass = klass->generic_class->container_class;
12701 MonoDynamicGenericClass *dgclass;
12704 mono_error_init (error);
12706 if (klass->wastypebuilder)
12709 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12710 if (klass->parent != gklass->parent) {
12711 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12712 if (mono_error_ok (error)) {
12713 MonoClass *parent = mono_class_from_mono_type (parent_type);
12714 mono_metadata_free_type (parent_type);
12715 if (parent != klass->parent) {
12716 /*fool mono_class_setup_parent*/
12717 klass->supertypes = NULL;
12718 mono_class_setup_parent (klass, parent);
12721 if (gklass->wastypebuilder)
12722 klass->wastypebuilder = TRUE;
12727 if (!dgclass->initialized)
12730 if (klass->method.count != gklass->method.count) {
12731 klass->method.count = gklass->method.count;
12732 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12734 for (i = 0; i < klass->method.count; i++) {
12735 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12736 gklass->methods [i], klass, mono_class_get_context (klass), error);
12737 mono_error_assert_ok (error);
12741 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12742 klass->interface_count = gklass->interface_count;
12743 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12744 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12746 for (i = 0; i < gklass->interface_count; ++i) {
12747 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12748 return_val_if_nok (error, FALSE);
12750 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12751 mono_metadata_free_type (iface_type);
12753 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12756 klass->interfaces_inited = 1;
12759 if (klass->field.count != gklass->field.count) {
12760 klass->field.count = gklass->field.count;
12761 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12763 for (i = 0; i < klass->field.count; i++) {
12764 klass->fields [i] = gklass->fields [i];
12765 klass->fields [i].parent = klass;
12766 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12767 return_val_if_nok (error, FALSE);
12771 /*We can only finish with this klass once it's parent has as well*/
12772 if (gklass->wastypebuilder)
12773 klass->wastypebuilder = TRUE;
12778 * ensure_generic_class_runtime_vtable:
12779 * @klass a generic class
12780 * @error set on error
12782 * Ensures that the generic container of @klass has a vtable and
12783 * returns TRUE on success. On error returns FALSE and sets @error.
12786 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12788 MonoClass *gklass = klass->generic_class->container_class;
12790 mono_error_init (error);
12792 if (!ensure_runtime_vtable (gklass, error))
12795 return fix_partial_generic_class (klass, error);
12799 * ensure_runtime_vtable:
12801 * @error set on error
12803 * Ensures that @klass has a vtable and returns TRUE on success. On
12804 * error returns FALSE and sets @error.
12807 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12809 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12812 mono_error_init (error);
12814 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12817 if (!ensure_runtime_vtable (klass->parent, error))
12821 num = tb->ctors? mono_array_length (tb->ctors): 0;
12822 num += tb->num_methods;
12823 klass->method.count = num;
12824 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12825 num = tb->ctors? mono_array_length (tb->ctors): 0;
12826 for (i = 0; i < num; ++i) {
12827 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12830 klass->methods [i] = ctor;
12832 num = tb->num_methods;
12834 for (i = 0; i < num; ++i) {
12835 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12838 klass->methods [j++] = meth;
12841 if (tb->interfaces) {
12842 klass->interface_count = mono_array_length (tb->interfaces);
12843 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12844 for (i = 0; i < klass->interface_count; ++i) {
12845 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12846 return_val_if_nok (error, FALSE);
12847 klass->interfaces [i] = mono_class_from_mono_type (iface);
12848 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12851 klass->interfaces_inited = 1;
12853 } else if (klass->generic_class){
12854 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12855 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12860 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12862 for (i = 0; i < klass->method.count; ++i) {
12863 MonoMethod *im = klass->methods [i];
12864 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12865 im->slot = slot_num++;
12868 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12869 mono_class_setup_interface_offsets (klass);
12870 mono_class_setup_interface_id (klass);
12874 * The generic vtable is needed even if image->run is not set since some
12875 * runtime code like ves_icall_Type_GetMethodsByName depends on
12876 * method->slot being defined.
12880 * tb->methods could not be freed since it is used for determining
12881 * overrides during dynamic vtable construction.
12888 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12890 mono_error_init (error);
12891 MonoClass *klass = mono_object_class (method);
12892 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12893 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12894 return sr_method->method;
12896 if (is_sre_method_builder (klass)) {
12897 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12898 return mb->mhandle;
12900 if (is_sre_method_on_tb_inst (klass)) {
12901 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12902 MonoMethod *result;
12903 /*FIXME move this to a proper method and unify with resolve_object*/
12904 if (m->method_args) {
12905 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12907 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12908 return_val_if_nok (error, NULL);
12909 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12910 MonoMethod *mono_method;
12912 if (is_sre_method_builder (mono_object_class (m->mb)))
12913 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12914 else if (is_sr_mono_method (mono_object_class (m->mb)))
12915 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12917 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)));
12919 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12924 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12929 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12931 MonoReflectionTypeBuilder *tb;
12933 MonoReflectionMethod *m;
12935 mono_error_init (error);
12937 *num_overrides = 0;
12939 g_assert (image_is_dynamic (klass->image));
12941 if (!mono_class_get_ref_info (klass))
12944 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12946 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12950 for (i = 0; i < tb->num_methods; ++i) {
12951 MonoReflectionMethodBuilder *mb =
12952 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12953 if (mb->override_methods)
12954 onum += mono_array_length (mb->override_methods);
12959 *overrides = g_new0 (MonoMethod*, onum * 2);
12962 for (i = 0; i < tb->num_methods; ++i) {
12963 MonoReflectionMethodBuilder *mb =
12964 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12965 if (mb->override_methods) {
12966 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12967 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12969 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12970 return_if_nok (error);
12971 (*overrides) [onum * 2 + 1] = mb->mhandle;
12973 g_assert (mb->mhandle);
12981 *num_overrides = onum;
12985 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12987 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12988 MonoReflectionFieldBuilder *fb;
12989 MonoClassField *field;
12990 MonoImage *image = klass->image;
12991 const char *p, *p2;
12993 guint32 len, idx, real_size = 0;
12995 klass->field.count = tb->num_fields;
12996 klass->field.first = 0;
12998 mono_error_init (error);
13000 if (tb->class_size) {
13001 if ((tb->packing_size & 0xffffff00) != 0) {
13002 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
13003 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
13006 klass->packing_size = tb->packing_size;
13007 real_size = klass->instance_size + tb->class_size;
13010 if (!klass->field.count) {
13011 klass->instance_size = MAX (klass->instance_size, real_size);
13015 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
13016 mono_class_alloc_ext (klass);
13017 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
13019 This is, guess what, a hack.
13020 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
13021 On the static path no field class is resolved, only types are built. This is the right thing to do
13023 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
13025 klass->size_inited = 1;
13027 for (i = 0; i < klass->field.count; ++i) {
13028 MonoArray *rva_data;
13029 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13030 field = &klass->fields [i];
13031 field->name = mono_string_to_utf8_image (image, fb->name, error);
13032 if (!mono_error_ok (error))
13035 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13036 return_if_nok (error);
13037 field->type = mono_metadata_type_dup (klass->image, type);
13038 field->type->attrs = fb->attrs;
13040 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13041 return_if_nok (error);
13044 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
13045 char *base = mono_array_addr (rva_data, char, 0);
13046 size_t size = mono_array_length (rva_data);
13047 char *data = (char *)mono_image_alloc (klass->image, size);
13048 memcpy (data, base, size);
13049 klass->ext->field_def_values [i].data = data;
13051 if (fb->offset != -1)
13052 field->offset = fb->offset;
13053 field->parent = klass;
13054 fb->handle = field;
13055 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13057 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13058 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13060 if (fb->def_value) {
13061 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13062 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13063 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13064 /* Copy the data from the blob since it might get realloc-ed */
13065 p = assembly->blob.data + idx;
13066 len = mono_metadata_decode_blob_size (p, &p2);
13068 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13069 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13073 klass->instance_size = MAX (klass->instance_size, real_size);
13074 mono_class_layout_fields (klass, klass->instance_size);
13078 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13080 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13081 MonoReflectionPropertyBuilder *pb;
13082 MonoImage *image = klass->image;
13083 MonoProperty *properties;
13086 mono_error_init (error);
13089 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13091 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13092 klass->ext->property.first = 0;
13094 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13095 klass->ext->properties = properties;
13096 for (i = 0; i < klass->ext->property.count; ++i) {
13097 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13098 properties [i].parent = klass;
13099 properties [i].attrs = pb->attrs;
13100 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13101 if (!mono_error_ok (error))
13103 if (pb->get_method)
13104 properties [i].get = pb->get_method->mhandle;
13105 if (pb->set_method)
13106 properties [i].set = pb->set_method->mhandle;
13108 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13109 if (pb->def_value) {
13111 const char *p, *p2;
13112 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13113 if (!klass->ext->prop_def_values)
13114 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13115 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13116 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13117 /* Copy the data from the blob since it might get realloc-ed */
13118 p = assembly->blob.data + idx;
13119 len = mono_metadata_decode_blob_size (p, &p2);
13121 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13122 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13127 static MonoReflectionEvent *
13128 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13130 mono_error_init (error);
13132 MonoEvent *event = g_new0 (MonoEvent, 1);
13135 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13136 if (!is_ok (error)) {
13140 klass = mono_class_from_mono_type (type);
13142 event->parent = klass;
13143 event->attrs = eb->attrs;
13144 event->name = mono_string_to_utf8_checked (eb->name, error);
13145 if (!is_ok (error)) {
13149 if (eb->add_method)
13150 event->add = eb->add_method->mhandle;
13151 if (eb->remove_method)
13152 event->remove = eb->remove_method->mhandle;
13153 if (eb->raise_method)
13154 event->raise = eb->raise_method->mhandle;
13156 #ifndef MONO_SMALL_CONFIG
13157 if (eb->other_methods) {
13159 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13160 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13161 MonoReflectionMethodBuilder *mb =
13162 mono_array_get (eb->other_methods,
13163 MonoReflectionMethodBuilder*, j);
13164 event->other [j] = mb->mhandle;
13169 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13170 if (!is_ok (error)) {
13171 #ifndef MONO_SMALL_CONFIG
13172 g_free (event->other);
13180 MonoReflectionEvent *
13181 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13184 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13185 mono_error_set_pending_exception (&error);
13190 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13192 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13193 MonoReflectionEventBuilder *eb;
13194 MonoImage *image = klass->image;
13198 mono_error_init (error);
13201 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13203 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13204 klass->ext->event.first = 0;
13206 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13207 klass->ext->events = events;
13208 for (i = 0; i < klass->ext->event.count; ++i) {
13209 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13210 events [i].parent = klass;
13211 events [i].attrs = eb->attrs;
13212 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13213 if (!mono_error_ok (error))
13215 if (eb->add_method)
13216 events [i].add = eb->add_method->mhandle;
13217 if (eb->remove_method)
13218 events [i].remove = eb->remove_method->mhandle;
13219 if (eb->raise_method)
13220 events [i].raise = eb->raise_method->mhandle;
13222 #ifndef MONO_SMALL_CONFIG
13223 if (eb->other_methods) {
13225 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13226 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13227 MonoReflectionMethodBuilder *mb =
13228 mono_array_get (eb->other_methods,
13229 MonoReflectionMethodBuilder*, j);
13230 events [i].other [j] = mb->mhandle;
13234 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13238 struct remove_instantiations_user_data
13245 remove_instantiations_of_and_ensure_contents (gpointer key,
13247 gpointer user_data)
13249 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13250 MonoType *type = (MonoType*)key;
13251 MonoClass *klass = data->klass;
13252 gboolean already_failed = !is_ok (data->error);
13254 MonoError *error = already_failed ? &lerror : data->error;
13256 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13257 MonoClass *inst_klass = mono_class_from_mono_type (type);
13258 //Ensure it's safe to use it.
13259 if (!fix_partial_generic_class (inst_klass, error)) {
13260 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13261 // Marked the class with failure, but since some other instantiation already failed,
13262 // just report that one, and swallow the error from this one.
13263 if (already_failed)
13264 mono_error_cleanup (error);
13272 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13274 mono_error_init (error);
13280 for (i = 0; i < mono_array_length (arr); ++i) {
13281 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13282 if (!mono_error_ok (error))
13287 MonoReflectionType*
13288 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13292 MonoDomain* domain;
13293 MonoReflectionType* res;
13296 mono_error_init (&error);
13298 domain = mono_object_domain (tb);
13299 klass = mono_class_from_mono_type (tb->type.type);
13302 * Check for user defined Type subclasses.
13304 RESOLVE_TYPE (tb->parent, &error);
13305 if (!is_ok (&error))
13306 goto failure_unlocked;
13307 check_array_for_usertypes (tb->interfaces, &error);
13308 if (!is_ok (&error))
13309 goto failure_unlocked;
13311 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13312 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13314 RESOLVE_TYPE (fb->type, &error);
13315 if (!is_ok (&error))
13316 goto failure_unlocked;
13317 check_array_for_usertypes (fb->modreq, &error);
13318 if (!is_ok (&error))
13319 goto failure_unlocked;
13320 check_array_for_usertypes (fb->modopt, &error);
13321 if (!is_ok (&error))
13322 goto failure_unlocked;
13323 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13324 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13325 if (!is_ok (&error))
13326 goto failure_unlocked;
13332 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13333 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13335 RESOLVE_TYPE (mb->rtype, &error);
13336 if (!is_ok (&error))
13337 goto failure_unlocked;
13338 check_array_for_usertypes (mb->return_modreq, &error);
13339 if (!is_ok (&error))
13340 goto failure_unlocked;
13341 check_array_for_usertypes (mb->return_modopt, &error);
13342 if (!is_ok (&error))
13343 goto failure_unlocked;
13344 check_array_for_usertypes (mb->parameters, &error);
13345 if (!is_ok (&error))
13346 goto failure_unlocked;
13347 if (mb->param_modreq)
13348 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13349 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13350 if (!is_ok (&error))
13351 goto failure_unlocked;
13353 if (mb->param_modopt)
13354 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13355 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13356 if (!is_ok (&error))
13357 goto failure_unlocked;
13363 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13364 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13366 check_array_for_usertypes (mb->parameters, &error);
13367 if (!is_ok (&error))
13368 goto failure_unlocked;
13369 if (mb->param_modreq)
13370 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13371 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13372 if (!is_ok (&error))
13373 goto failure_unlocked;
13375 if (mb->param_modopt)
13376 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13377 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13378 if (!is_ok (&error))
13379 goto failure_unlocked;
13385 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13388 * we need to lock the domain because the lock will be taken inside
13389 * So, we need to keep the locking order correct.
13391 mono_loader_lock ();
13392 mono_domain_lock (domain);
13393 if (klass->wastypebuilder) {
13394 mono_domain_unlock (domain);
13395 mono_loader_unlock ();
13397 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13398 mono_error_set_pending_exception (&error);
13403 * Fields to set in klass:
13404 * the various flags: delegate/unicode/contextbound etc.
13406 klass->flags = tb->attrs;
13407 klass->has_cctor = 1;
13409 mono_class_setup_parent (klass, klass->parent);
13410 /* fool mono_class_setup_supertypes */
13411 klass->supertypes = NULL;
13412 mono_class_setup_supertypes (klass);
13413 mono_class_setup_mono_type (klass);
13416 if (!((MonoDynamicImage*)klass->image)->run) {
13417 if (klass->generic_container) {
13418 /* FIXME: The code below can't handle generic classes */
13419 klass->wastypebuilder = TRUE;
13420 mono_loader_unlock ();
13421 mono_domain_unlock (domain);
13423 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13424 mono_error_set_pending_exception (&error);
13431 /* enums are done right away */
13432 if (!klass->enumtype)
13433 if (!ensure_runtime_vtable (klass, &error))
13436 if (tb->subtypes) {
13437 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13438 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13439 mono_class_alloc_ext (klass);
13440 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13441 if (!is_ok (&error)) goto failure;
13442 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13446 klass->nested_classes_inited = TRUE;
13448 /* fields and object layout */
13449 if (klass->parent) {
13450 if (!klass->parent->size_inited)
13451 mono_class_init (klass->parent);
13452 klass->instance_size = klass->parent->instance_size;
13453 klass->sizes.class_size = 0;
13454 klass->min_align = klass->parent->min_align;
13455 /* if the type has no fields we won't call the field_setup
13456 * routine which sets up klass->has_references.
13458 klass->has_references |= klass->parent->has_references;
13460 klass->instance_size = sizeof (MonoObject);
13461 klass->min_align = 1;
13464 /* FIXME: handle packing_size and instance_size */
13465 typebuilder_setup_fields (klass, &error);
13466 if (!mono_error_ok (&error))
13468 typebuilder_setup_properties (klass, &error);
13469 if (!mono_error_ok (&error))
13472 typebuilder_setup_events (klass, &error);
13473 if (!mono_error_ok (&error))
13476 klass->wastypebuilder = TRUE;
13479 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13480 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13481 * we want to return normal System.MonoType objects, so clear these out from the cache.
13483 * Together with this we must ensure the contents of all instances to match the created type.
13485 if (domain->type_hash && klass->generic_container) {
13486 struct remove_instantiations_user_data data;
13487 data.klass = klass;
13488 data.error = &error;
13489 mono_error_assert_ok (&error);
13490 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13491 if (!is_ok (&error))
13495 mono_domain_unlock (domain);
13496 mono_loader_unlock ();
13498 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13499 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13500 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13501 goto failure_unlocked;
13504 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13505 if (!is_ok (&error))
13506 goto failure_unlocked;
13508 g_assert (res != (MonoReflectionType*)tb);
13513 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13514 klass->wastypebuilder = TRUE;
13515 mono_domain_unlock (domain);
13516 mono_loader_unlock ();
13518 mono_error_set_pending_exception (&error);
13523 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13525 MonoGenericParamFull *param;
13529 mono_error_init (error);
13531 image = &gparam->tbuilder->module->dynamic_image->image;
13533 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13535 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13536 mono_error_assert_ok (error);
13537 param->param.num = gparam->index;
13539 if (gparam->mbuilder) {
13540 if (!gparam->mbuilder->generic_container) {
13541 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13542 return_val_if_nok (error, FALSE);
13544 MonoClass *klass = mono_class_from_mono_type (tb);
13545 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13546 gparam->mbuilder->generic_container->is_method = TRUE;
13548 * Cannot set owner.method, since the MonoMethod is not created yet.
13549 * Set the image field instead, so type_in_image () works.
13551 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13552 gparam->mbuilder->generic_container->owner.image = klass->image;
13554 param->param.owner = gparam->mbuilder->generic_container;
13555 } else if (gparam->tbuilder) {
13556 if (!gparam->tbuilder->generic_container) {
13557 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13558 return_val_if_nok (error, FALSE);
13559 MonoClass *klass = mono_class_from_mono_type (tb);
13560 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13561 gparam->tbuilder->generic_container->owner.klass = klass;
13563 param->param.owner = gparam->tbuilder->generic_container;
13566 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13568 gparam->type.type = &pklass->byval_arg;
13570 mono_class_set_ref_info (pklass, gparam);
13571 mono_image_append_class_to_reflection_info_set (pklass);
13577 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13580 (void) reflection_initialize_generic_parameter (gparam, &error);
13581 mono_error_set_pending_exception (&error);
13586 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13588 MonoReflectionModuleBuilder *module = sig->module;
13589 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13590 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13595 mono_error_init (error);
13597 check_array_for_usertypes (sig->arguments, error);
13598 return_val_if_nok (error, NULL);
13600 sigbuffer_init (&buf, 32);
13602 sigbuffer_add_value (&buf, 0x07);
13603 sigbuffer_add_value (&buf, na);
13604 if (assembly != NULL){
13605 for (i = 0; i < na; ++i) {
13606 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13607 encode_reflection_type (assembly, type, &buf, error);
13608 if (!is_ok (error)) goto fail;
13612 buflen = buf.p - buf.buf;
13613 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13614 if (!is_ok (error)) goto fail;
13615 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13616 sigbuffer_free (&buf);
13619 sigbuffer_free (&buf);
13624 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13627 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13628 mono_error_set_pending_exception (&error);
13633 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13635 MonoDynamicImage *assembly = sig->module->dynamic_image;
13636 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13641 mono_error_init (error);
13643 check_array_for_usertypes (sig->arguments, error);
13644 return_val_if_nok (error, NULL);
13646 sigbuffer_init (&buf, 32);
13648 sigbuffer_add_value (&buf, 0x06);
13649 for (i = 0; i < na; ++i) {
13650 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13651 encode_reflection_type (assembly, type, &buf, error);
13652 if (!is_ok (error))
13656 buflen = buf.p - buf.buf;
13657 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13658 if (!is_ok (error)) goto fail;
13659 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13660 sigbuffer_free (&buf);
13664 sigbuffer_free (&buf);
13669 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13672 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13673 mono_error_set_pending_exception (&error);
13678 MonoMethod *handle;
13679 MonoDomain *domain;
13680 } DynamicMethodReleaseData;
13683 * The runtime automatically clean up those after finalization.
13685 static MonoReferenceQueue *dynamic_method_queue;
13688 free_dynamic_method (void *dynamic_method)
13690 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13691 MonoDomain *domain = data->domain;
13692 MonoMethod *method = data->handle;
13695 mono_domain_lock (domain);
13696 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13697 g_hash_table_remove (domain->method_to_dyn_method, method);
13698 mono_domain_unlock (domain);
13699 g_assert (dis_link);
13700 mono_gchandle_free (dis_link);
13702 mono_runtime_free_method (domain, method);
13707 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13709 MonoReferenceQueue *queue;
13710 MonoMethod *handle;
13711 DynamicMethodReleaseData *release_data;
13712 ReflectionMethodBuilder rmb;
13713 MonoMethodSignature *sig;
13715 MonoDomain *domain;
13719 mono_error_init (error);
13721 if (mono_runtime_is_shutting_down ()) {
13722 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13726 if (!(queue = dynamic_method_queue)) {
13727 mono_loader_lock ();
13728 if (!(queue = dynamic_method_queue))
13729 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13730 mono_loader_unlock ();
13733 sig = dynamic_method_to_signature (mb, error);
13734 return_val_if_nok (error, FALSE);
13736 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13739 * Resolve references.
13742 * Every second entry in the refs array is reserved for storing handle_class,
13743 * which is needed by the ldtoken implementation in the JIT.
13745 rmb.nrefs = mb->nrefs;
13746 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13747 for (i = 0; i < mb->nrefs; i += 2) {
13748 MonoClass *handle_class;
13750 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13752 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13753 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13755 * The referenced DynamicMethod should already be created by the managed
13756 * code, except in the case of circular references. In that case, we store
13757 * method in the refs array, and fix it up later when the referenced
13758 * DynamicMethod is created.
13760 if (method->mhandle) {
13761 ref = method->mhandle;
13763 /* FIXME: GC object stored in unmanaged memory */
13766 /* FIXME: GC object stored in unmanaged memory */
13767 method->referenced_by = g_slist_append (method->referenced_by, mb);
13769 handle_class = mono_defaults.methodhandle_class;
13771 MonoException *ex = NULL;
13772 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13773 if (!is_ok (error)) {
13778 ex = mono_get_exception_type_load (NULL, NULL);
13779 else if (mono_security_core_clr_enabled ())
13780 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13784 mono_error_set_exception_instance (error, ex);
13789 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13790 rmb.refs [i + 1] = handle_class;
13794 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13795 if (!is_ok (error)) {
13799 klass = mono_class_from_mono_type (owner_type);
13801 klass = mono_defaults.object_class;
13804 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13806 return_val_if_nok (error, FALSE);
13808 release_data = g_new (DynamicMethodReleaseData, 1);
13809 release_data->handle = handle;
13810 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13811 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13812 g_free (release_data);
13814 /* Fix up refs entries pointing at us */
13815 for (l = mb->referenced_by; l; l = l->next) {
13816 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13817 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13820 g_assert (method->mhandle);
13822 data = (gpointer*)wrapper->method_data;
13823 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13824 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13825 data [i + 1] = mb->mhandle;
13828 g_slist_free (mb->referenced_by);
13830 /* ilgen is no longer needed */
13833 domain = mono_domain_get ();
13834 mono_domain_lock (domain);
13835 if (!domain->method_to_dyn_method)
13836 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13837 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13838 mono_domain_unlock (domain);
13844 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13847 (void) reflection_create_dynamic_method (mb, &error);
13848 mono_error_set_pending_exception (&error);
13851 #endif /* DISABLE_REFLECTION_EMIT */
13855 * mono_reflection_is_valid_dynamic_token:
13857 * Returns TRUE if token is valid.
13861 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13863 return lookup_dyn_token (image, token) != NULL;
13866 MonoMethodSignature *
13867 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13869 MonoMethodSignature *sig;
13870 g_assert (image_is_dynamic (image));
13872 mono_error_init (error);
13874 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13878 return mono_method_signature_checked (method, error);
13881 #ifndef DISABLE_REFLECTION_EMIT
13884 * mono_reflection_lookup_dynamic_token:
13886 * Finish the Builder object pointed to by TOKEN and return the corresponding
13887 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13888 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13891 * LOCKING: Take the loader lock
13894 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13896 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13900 mono_error_init (error);
13902 obj = lookup_dyn_token (assembly, token);
13905 g_error ("Could not find required dynamic token 0x%08x", token);
13907 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13913 handle_class = &klass;
13914 gpointer result = resolve_object (image, obj, handle_class, context, error);
13919 * ensure_complete_type:
13921 * Ensure that KLASS is completed if it is a dynamic type, or references
13925 ensure_complete_type (MonoClass *klass, MonoError *error)
13927 mono_error_init (error);
13929 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13930 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13932 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13933 return_if_nok (error);
13935 // Asserting here could break a lot of code
13936 //g_assert (klass->wastypebuilder);
13939 if (klass->generic_class) {
13940 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13943 for (i = 0; i < inst->type_argc; ++i) {
13944 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13945 return_if_nok (error);
13951 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13953 gpointer result = NULL;
13955 mono_error_init (error);
13957 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13958 result = mono_string_intern_checked ((MonoString*)obj, error);
13959 return_val_if_nok (error, NULL);
13960 *handle_class = mono_defaults.string_class;
13962 } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13963 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13964 return_val_if_nok (error, NULL);
13965 MonoClass *mc = mono_class_from_mono_type (type);
13966 if (!mono_class_init (mc)) {
13967 mono_error_set_for_class_failure (error, mc);
13972 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13973 return_val_if_nok (error, NULL);
13975 result = mono_class_from_mono_type (inflated);
13976 mono_metadata_free_type (inflated);
13978 result = mono_class_from_mono_type (type);
13980 *handle_class = mono_defaults.typehandle_class;
13982 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13983 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13984 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13985 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13986 result = ((MonoReflectionMethod*)obj)->method;
13988 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13989 mono_error_assert_ok (error);
13991 *handle_class = mono_defaults.methodhandle_class;
13993 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13994 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13995 result = mb->mhandle;
13997 /* Type is not yet created */
13998 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
14000 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14001 return_val_if_nok (error, NULL);
14004 * Hopefully this has been filled in by calling CreateType() on the
14008 * TODO: This won't work if the application finishes another
14009 * TypeBuilder instance instead of this one.
14011 result = mb->mhandle;
14014 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14015 mono_error_assert_ok (error);
14017 *handle_class = mono_defaults.methodhandle_class;
14018 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
14019 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
14021 result = cb->mhandle;
14023 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
14025 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14026 return_val_if_nok (error, NULL);
14027 result = cb->mhandle;
14030 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14031 mono_error_assert_ok (error);
14033 *handle_class = mono_defaults.methodhandle_class;
14034 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
14035 MonoClassField *field = ((MonoReflectionField*)obj)->field;
14037 ensure_complete_type (field->parent, error);
14038 return_val_if_nok (error, NULL);
14041 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
14042 return_val_if_nok (error, NULL);
14044 MonoClass *klass = mono_class_from_mono_type (inflated);
14045 MonoClassField *inflated_field;
14046 gpointer iter = NULL;
14047 mono_metadata_free_type (inflated);
14048 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
14049 if (!strcmp (field->name, inflated_field->name))
14052 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
14053 result = inflated_field;
14057 *handle_class = mono_defaults.fieldhandle_class;
14059 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14060 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14061 result = fb->handle;
14064 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14066 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14067 return_val_if_nok (error, NULL);
14068 result = fb->handle;
14071 if (fb->handle && fb->handle->parent->generic_container) {
14072 MonoClass *klass = fb->handle->parent;
14073 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14074 return_val_if_nok (error, NULL);
14076 MonoClass *inflated = mono_class_from_mono_type (type);
14078 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14080 mono_metadata_free_type (type);
14082 *handle_class = mono_defaults.fieldhandle_class;
14083 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14084 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14085 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14086 return_val_if_nok (error, NULL);
14089 klass = type->data.klass;
14090 if (klass->wastypebuilder) {
14091 /* Already created */
14095 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14096 return_val_if_nok (error, NULL);
14097 result = type->data.klass;
14100 *handle_class = mono_defaults.typehandle_class;
14101 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14102 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14103 MonoMethodSignature *sig;
14106 if (helper->arguments)
14107 nargs = mono_array_length (helper->arguments);
14111 sig = mono_metadata_signature_alloc (image, nargs);
14112 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14113 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14115 if (helper->unmanaged_call_conv) { /* unmanaged */
14116 sig->call_convention = helper->unmanaged_call_conv - 1;
14117 sig->pinvoke = TRUE;
14118 } else if (helper->call_conv & 0x02) {
14119 sig->call_convention = MONO_CALL_VARARG;
14121 sig->call_convention = MONO_CALL_DEFAULT;
14124 sig->param_count = nargs;
14125 /* TODO: Copy type ? */
14126 sig->ret = helper->return_type->type;
14127 for (i = 0; i < nargs; ++i) {
14128 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14129 if (!is_ok (error)) {
14130 image_g_free (image, sig);
14136 *handle_class = NULL;
14137 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14138 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14139 /* Already created by the managed code */
14140 g_assert (method->mhandle);
14141 result = method->mhandle;
14142 *handle_class = mono_defaults.methodhandle_class;
14143 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14144 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14145 return_val_if_nok (error, NULL);
14146 type = mono_class_inflate_generic_type_checked (type, context, error);
14147 return_val_if_nok (error, NULL);
14149 result = mono_class_from_mono_type (type);
14150 *handle_class = mono_defaults.typehandle_class;
14152 mono_metadata_free_type (type);
14153 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14154 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14155 return_val_if_nok (error, NULL);
14156 type = mono_class_inflate_generic_type_checked (type, context, error);
14157 return_val_if_nok (error, NULL);
14159 result = mono_class_from_mono_type (type);
14160 *handle_class = mono_defaults.typehandle_class;
14162 mono_metadata_free_type (type);
14163 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14164 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14165 MonoClass *inflated;
14167 MonoClassField *field;
14169 if (is_sre_field_builder (mono_object_class (f->fb)))
14170 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14171 else if (is_sr_mono_field (mono_object_class (f->fb)))
14172 field = ((MonoReflectionField*)f->fb)->field;
14174 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)));
14176 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14177 return_val_if_nok (error, NULL);
14178 type = mono_class_inflate_generic_type_checked (finst, context, error);
14179 return_val_if_nok (error, NULL);
14181 inflated = mono_class_from_mono_type (type);
14183 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14184 ensure_complete_type (field->parent, error);
14185 if (!is_ok (error)) {
14186 mono_metadata_free_type (type);
14191 mono_metadata_free_type (type);
14192 *handle_class = mono_defaults.fieldhandle_class;
14193 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14194 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14195 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14196 return_val_if_nok (error, NULL);
14197 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14198 return_val_if_nok (error, NULL);
14200 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14201 MonoMethod *method;
14203 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14204 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14205 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14206 method = ((MonoReflectionMethod *)c->cb)->method;
14208 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)));
14210 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14211 *handle_class = mono_defaults.methodhandle_class;
14212 mono_metadata_free_type (type);
14213 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14214 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14215 if (m->method_args) {
14216 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14217 return_val_if_nok (error, NULL);
14219 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14220 mono_error_assert_ok (error);
14223 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14224 return_val_if_nok (error, NULL);
14225 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14226 return_val_if_nok (error, NULL);
14228 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14229 MonoMethod *method;
14231 if (is_sre_method_builder (mono_object_class (m->mb)))
14232 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14233 else if (is_sr_mono_method (mono_object_class (m->mb)))
14234 method = ((MonoReflectionMethod *)m->mb)->method;
14236 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)));
14238 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14239 mono_metadata_free_type (type);
14241 *handle_class = mono_defaults.methodhandle_class;
14242 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14243 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14246 MonoMethod *method;
14250 mtype = mono_reflection_type_get_handle (m->parent, error);
14251 return_val_if_nok (error, NULL);
14252 klass = mono_class_from_mono_type (mtype);
14254 /* Find the method */
14256 name = mono_string_to_utf8_checked (m->name, error);
14257 return_val_if_nok (error, NULL);
14259 while ((method = mono_class_get_methods (klass, &iter))) {
14260 if (!strcmp (method->name, name))
14267 // FIXME: Check parameters/return value etc. match
14270 *handle_class = mono_defaults.methodhandle_class;
14271 } else if (is_sre_array (mono_object_get_class(obj)) ||
14272 is_sre_byref (mono_object_get_class(obj)) ||
14273 is_sre_pointer (mono_object_get_class(obj))) {
14274 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14275 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14276 return_val_if_nok (error, NULL);
14279 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14280 return_val_if_nok (error, NULL);
14282 result = mono_class_from_mono_type (inflated);
14283 mono_metadata_free_type (inflated);
14285 result = mono_class_from_mono_type (type);
14287 *handle_class = mono_defaults.typehandle_class;
14289 g_print ("%s\n", obj->vtable->klass->name);
14290 g_assert_not_reached ();
14295 #else /* DISABLE_REFLECTION_EMIT */
14298 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14300 g_assert_not_reached ();
14305 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14307 g_assert_not_reached ();
14311 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14313 g_assert_not_reached ();
14317 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14319 g_assert_not_reached ();
14324 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14326 g_assert_not_reached ();
14330 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14332 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14336 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14338 g_assert_not_reached ();
14342 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14344 g_assert_not_reached ();
14347 MonoReflectionModule *
14348 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14350 g_assert_not_reached ();
14355 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14357 g_assert_not_reached ();
14362 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14364 g_assert_not_reached ();
14369 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14370 gboolean create_open_instance, gboolean register_token, MonoError *error)
14372 g_assert_not_reached ();
14377 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14382 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14384 g_assert_not_reached ();
14388 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14390 mono_error_init (error);
14392 *num_overrides = 0;
14395 MonoReflectionEvent *
14396 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14398 g_assert_not_reached ();
14402 MonoReflectionType*
14403 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14405 g_assert_not_reached ();
14410 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14412 g_assert_not_reached ();
14416 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14418 g_assert_not_reached ();
14423 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14425 g_assert_not_reached ();
14430 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14435 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14437 mono_error_init (error);
14442 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14444 mono_error_init (error);
14451 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14453 g_assert_not_reached ();
14456 #endif /* DISABLE_REFLECTION_EMIT */
14458 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14459 const static guint32 declsec_flags_map[] = {
14460 0x00000000, /* empty */
14461 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14462 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14463 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14464 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14465 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14466 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14467 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14468 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14469 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14470 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14471 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14472 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14473 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14474 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14475 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14476 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14477 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14478 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14482 * Returns flags that includes all available security action associated to the handle.
14483 * @token: metadata token (either for a class or a method)
14484 * @image: image where resides the metadata.
14487 mono_declsec_get_flags (MonoImage *image, guint32 token)
14489 int index = mono_metadata_declsec_from_index (image, token);
14490 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14491 guint32 result = 0;
14495 /* HasSecurity can be present for other, not specially encoded, attributes,
14496 e.g. SuppressUnmanagedCodeSecurityAttribute */
14500 for (i = index; i < t->rows; i++) {
14501 guint32 cols [MONO_DECL_SECURITY_SIZE];
14503 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14504 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14507 action = cols [MONO_DECL_SECURITY_ACTION];
14508 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14509 result |= declsec_flags_map [action];
14511 g_assert_not_reached ();
14518 * Get the security actions (in the form of flags) associated with the specified method.
14520 * @method: The method for which we want the declarative security flags.
14521 * Return the declarative security flags for the method (only).
14523 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14524 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14527 mono_declsec_flags_from_method (MonoMethod *method)
14529 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14530 /* FIXME: No cache (for the moment) */
14531 guint32 idx = mono_method_get_index (method);
14532 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14533 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14534 return mono_declsec_get_flags (method->klass->image, idx);
14540 * Get the security actions (in the form of flags) associated with the specified class.
14542 * @klass: The class for which we want the declarative security flags.
14543 * Return the declarative security flags for the class.
14545 * Note: We cache the flags inside the MonoClass structure as this will get
14546 * called very often (at least for each method).
14549 mono_declsec_flags_from_class (MonoClass *klass)
14551 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14552 if (!klass->ext || !klass->ext->declsec_flags) {
14555 idx = mono_metadata_token_index (klass->type_token);
14556 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14557 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14558 mono_loader_lock ();
14559 mono_class_alloc_ext (klass);
14560 mono_loader_unlock ();
14561 /* we cache the flags on classes */
14562 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14564 return klass->ext->declsec_flags;
14570 * Get the security actions (in the form of flags) associated with the specified assembly.
14572 * @assembly: The assembly for which we want the declarative security flags.
14573 * Return the declarative security flags for the assembly.
14576 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14578 guint32 idx = 1; /* there is only one assembly */
14579 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14580 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14581 return mono_declsec_get_flags (assembly->image, idx);
14586 * Fill actions for the specific index (which may either be an encoded class token or
14587 * an encoded method token) from the metadata image.
14588 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14591 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14592 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14594 MonoBoolean result = FALSE;
14596 guint32 cols [MONO_DECL_SECURITY_SIZE];
14597 int index = mono_metadata_declsec_from_index (image, token);
14600 t = &image->tables [MONO_TABLE_DECLSECURITY];
14601 for (i = index; i < t->rows; i++) {
14602 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14604 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14607 /* if present only replace (class) permissions with method permissions */
14608 /* if empty accept either class or method permissions */
14609 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14610 if (!actions->demand.blob) {
14611 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14612 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14613 actions->demand.blob = (char*) (blob + 2);
14614 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14617 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14618 if (!actions->noncasdemand.blob) {
14619 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14620 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14621 actions->noncasdemand.blob = (char*) (blob + 2);
14622 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14625 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14626 if (!actions->demandchoice.blob) {
14627 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14628 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14629 actions->demandchoice.blob = (char*) (blob + 2);
14630 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14640 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14641 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14643 guint32 idx = mono_metadata_token_index (klass->type_token);
14644 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14645 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14646 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14650 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14651 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14653 guint32 idx = mono_method_get_index (method);
14654 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14655 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14656 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14660 * Collect all actions (that requires to generate code in mini) assigned for
14661 * the specified method.
14662 * Note: Don't use the content of actions if the function return FALSE.
14665 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14667 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14668 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14669 MonoBoolean result = FALSE;
14672 /* quick exit if no declarative security is present in the metadata */
14673 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14676 /* we want the original as the wrapper is "free" of the security informations */
14677 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14678 method = mono_marshal_method_from_wrapper (method);
14683 /* First we look for method-level attributes */
14684 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14685 mono_class_init (method->klass);
14686 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14688 result = mono_declsec_get_method_demands_params (method, demands,
14689 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14692 /* Here we use (or create) the class declarative cache to look for demands */
14693 flags = mono_declsec_flags_from_class (method->klass);
14694 if (flags & mask) {
14696 mono_class_init (method->klass);
14697 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14699 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14700 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14703 /* The boolean return value is used as a shortcut in case nothing needs to
14704 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14710 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14712 * Note: Don't use the content of actions if the function return FALSE.
14715 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14717 MonoBoolean result = FALSE;
14720 /* quick exit if no declarative security is present in the metadata */
14721 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14724 /* we want the original as the wrapper is "free" of the security informations */
14725 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14726 method = mono_marshal_method_from_wrapper (method);
14731 /* results are independant - zeroize both */
14732 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14733 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14735 /* First we look for method-level attributes */
14736 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14737 mono_class_init (method->klass);
14739 result = mono_declsec_get_method_demands_params (method, cmethod,
14740 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14743 /* Here we use (or create) the class declarative cache to look for demands */
14744 flags = mono_declsec_flags_from_class (method->klass);
14745 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14746 mono_class_init (method->klass);
14748 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14749 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14756 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14758 * @klass The inherited class - this is the class that provides the security check (attributes)
14760 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14762 * Note: Don't use the content of actions if the function return FALSE.
14765 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14767 MonoBoolean result = FALSE;
14770 /* quick exit if no declarative security is present in the metadata */
14771 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14774 /* Here we use (or create) the class declarative cache to look for demands */
14775 flags = mono_declsec_flags_from_class (klass);
14776 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14777 mono_class_init (klass);
14778 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14780 result |= mono_declsec_get_class_demands_params (klass, demands,
14781 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14788 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14790 * Note: Don't use the content of actions if the function return FALSE.
14793 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14795 /* quick exit if no declarative security is present in the metadata */
14796 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14799 /* we want the original as the wrapper is "free" of the security informations */
14800 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14801 method = mono_marshal_method_from_wrapper (method);
14806 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14807 mono_class_init (method->klass);
14808 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14810 return mono_declsec_get_method_demands_params (method, demands,
14811 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14818 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14820 guint32 cols [MONO_DECL_SECURITY_SIZE];
14824 int index = mono_metadata_declsec_from_index (image, token);
14828 t = &image->tables [MONO_TABLE_DECLSECURITY];
14829 for (i = index; i < t->rows; i++) {
14830 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14832 /* shortcut - index are ordered */
14833 if (token != cols [MONO_DECL_SECURITY_PARENT])
14836 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14837 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14838 entry->blob = (char*) (metadata + 2);
14839 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14848 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14850 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14851 guint32 idx = mono_method_get_index (method);
14852 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14853 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14854 return get_declsec_action (method->klass->image, idx, action, entry);
14860 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14863 guint32 flags = mono_declsec_flags_from_class (klass);
14864 if (declsec_flags_map [action] & flags) {
14865 guint32 idx = mono_metadata_token_index (klass->type_token);
14866 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14867 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14868 return get_declsec_action (klass->image, idx, action, entry);
14874 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14876 guint32 idx = 1; /* there is only one assembly */
14877 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14878 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14880 return get_declsec_action (assembly->image, idx, action, entry);
14884 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14886 MonoObject *res, *exc;
14888 static MonoMethod *method = NULL;
14890 mono_error_init (error);
14892 if (method == NULL) {
14893 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14898 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14899 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14901 g_assert (mono_class_get_ref_info (klass));
14902 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14904 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14905 return_val_if_nok (error, FALSE);
14907 MonoError inner_error;
14908 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14910 if (exc || !is_ok (&inner_error)) {
14911 mono_error_cleanup (&inner_error);
14914 return *(MonoBoolean*)mono_object_unbox (res);
14918 * mono_reflection_type_get_type:
14919 * @reftype: the System.Type object
14921 * Returns the MonoType* associated with the C# System.Type object @reftype.
14924 mono_reflection_type_get_type (MonoReflectionType *reftype)
14926 g_assert (reftype);
14929 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14930 mono_error_assert_ok (&error);
14935 * mono_reflection_assembly_get_assembly:
14936 * @refassembly: the System.Reflection.Assembly object
14938 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14941 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14943 g_assert (refassembly);
14945 return refassembly->assembly;