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)
297 MONO_PREPARE_BLOCKING;
298 mono_image_lock ((MonoImage*)image);
299 MONO_FINISH_BLOCKING;
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)
532 MONO_REQ_GC_UNSAFE_MODE;
534 char *name = mono_string_to_utf8 (str);
536 idx = string_heap_insert (sh, name);
541 #ifndef DISABLE_REFLECTION_EMIT
543 string_heap_init (MonoDynamicStream *sh)
545 MONO_REQ_GC_NEUTRAL_MODE;
548 sh->alloc_size = 4096;
549 sh->data = (char *)g_malloc (4096);
550 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
551 string_heap_insert (sh, "");
556 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
558 MONO_REQ_GC_NEUTRAL_MODE;
562 make_room_in_stream (stream, stream->index + len);
563 memcpy (stream->data + stream->index, data, len);
565 stream->index += len;
567 * align index? Not without adding an additional param that controls it since
568 * we may store a blob value in pieces.
574 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
576 MONO_REQ_GC_NEUTRAL_MODE;
580 make_room_in_stream (stream, stream->index + len);
581 memset (stream->data + stream->index, 0, len);
583 stream->index += len;
588 stream_data_align (MonoDynamicStream *stream)
590 MONO_REQ_GC_NEUTRAL_MODE;
593 guint32 count = stream->index % 4;
595 /* we assume the stream data will be aligned */
597 mono_image_add_stream_data (stream, buf, 4 - count);
600 #ifndef DISABLE_REFLECTION_EMIT
602 mono_blob_entry_hash (const char* str)
604 MONO_REQ_GC_NEUTRAL_MODE;
608 len = mono_metadata_decode_blob_size (str, &str);
612 for (str += 1; str < end; str++)
613 h = (h << 5) - h + *str;
621 mono_blob_entry_equal (const char *str1, const char *str2) {
622 MONO_REQ_GC_NEUTRAL_MODE;
627 len = mono_metadata_decode_blob_size (str1, &end1);
628 len2 = mono_metadata_decode_blob_size (str2, &end2);
631 return memcmp (end1, end2, len) == 0;
635 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
637 MONO_REQ_GC_NEUTRAL_MODE;
641 gpointer oldkey, oldval;
643 copy = (char *)g_malloc (s1+s2);
644 memcpy (copy, b1, s1);
645 memcpy (copy + s1, b2, s2);
646 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
648 idx = GPOINTER_TO_UINT (oldval);
650 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
651 mono_image_add_stream_data (&assembly->blob, b2, s2);
652 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
658 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
660 MONO_REQ_GC_NEUTRAL_MODE;
664 guint32 size = buf->p - buf->buf;
666 g_assert (size <= (buf->end - buf->buf));
667 mono_metadata_encode_value (size, b, &b);
668 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
672 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
673 * dest may be misaligned.
676 swap_with_size (char *dest, const char* val, int len, int nelem) {
677 MONO_REQ_GC_NEUTRAL_MODE;
678 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
681 for (elem = 0; elem < nelem; ++elem) {
707 g_assert_not_reached ();
713 memcpy (dest, val, len * nelem);
718 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
720 MONO_REQ_GC_UNSAFE_MODE;
724 guint32 idx = 0, len;
726 len = str->length * 2;
727 mono_metadata_encode_value (len, b, &b);
728 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
730 char *swapped = g_malloc (2 * mono_string_length (str));
731 const char *p = (const char*)mono_string_chars (str);
733 swap_with_size (swapped, p, 2, mono_string_length (str));
734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
743 #ifndef DISABLE_REFLECTION_EMIT
745 default_class_from_mono_type (MonoType *type)
747 MONO_REQ_GC_NEUTRAL_MODE;
749 switch (type->type) {
750 case MONO_TYPE_OBJECT:
751 return mono_defaults.object_class;
753 return mono_defaults.void_class;
754 case MONO_TYPE_BOOLEAN:
755 return mono_defaults.boolean_class;
757 return mono_defaults.char_class;
759 return mono_defaults.sbyte_class;
761 return mono_defaults.byte_class;
763 return mono_defaults.int16_class;
765 return mono_defaults.uint16_class;
767 return mono_defaults.int32_class;
769 return mono_defaults.uint32_class;
771 return mono_defaults.int_class;
773 return mono_defaults.uint_class;
775 return mono_defaults.int64_class;
777 return mono_defaults.uint64_class;
779 return mono_defaults.single_class;
781 return mono_defaults.double_class;
782 case MONO_TYPE_STRING:
783 return mono_defaults.string_class;
785 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
786 g_assert_not_reached ();
794 * mono_class_get_ref_info:
796 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
799 mono_class_get_ref_info (MonoClass *klass)
801 MONO_REQ_GC_UNSAFE_MODE;
803 if (klass->ref_info_handle == 0)
806 return mono_gchandle_get_target (klass->ref_info_handle);
810 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
812 MONO_REQ_GC_UNSAFE_MODE;
814 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
815 g_assert (klass->ref_info_handle != 0);
819 mono_class_free_ref_info (MonoClass *klass)
821 MONO_REQ_GC_NEUTRAL_MODE;
823 if (klass->ref_info_handle) {
824 mono_gchandle_free (klass->ref_info_handle);
825 klass->ref_info_handle = 0;
830 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
832 MONO_REQ_GC_NEUTRAL_MODE;
835 MonoGenericInst *class_inst;
840 class_inst = gclass->context.class_inst;
842 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
843 klass = gclass->container_class;
844 sigbuffer_add_value (buf, klass->byval_arg.type);
845 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
847 sigbuffer_add_value (buf, class_inst->type_argc);
848 for (i = 0; i < class_inst->type_argc; ++i)
849 encode_type (assembly, class_inst->type_argv [i], buf);
854 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
856 MONO_REQ_GC_NEUTRAL_MODE;
859 g_assert_not_reached ();
864 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
868 case MONO_TYPE_BOOLEAN:
882 case MONO_TYPE_STRING:
883 case MONO_TYPE_OBJECT:
884 case MONO_TYPE_TYPEDBYREF:
885 sigbuffer_add_value (buf, type->type);
888 sigbuffer_add_value (buf, type->type);
889 encode_type (assembly, type->data.type, buf);
891 case MONO_TYPE_SZARRAY:
892 sigbuffer_add_value (buf, type->type);
893 encode_type (assembly, &type->data.klass->byval_arg, buf);
895 case MONO_TYPE_VALUETYPE:
896 case MONO_TYPE_CLASS: {
897 MonoClass *k = mono_class_from_mono_type (type);
899 if (k->generic_container) {
900 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
901 encode_generic_class (assembly, gclass, buf);
904 * Make sure we use the correct type.
906 sigbuffer_add_value (buf, k->byval_arg.type);
908 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
909 * otherwise two typerefs could point to the same type, leading to
910 * verification errors.
912 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
916 case MONO_TYPE_ARRAY:
917 sigbuffer_add_value (buf, type->type);
918 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
919 sigbuffer_add_value (buf, type->data.array->rank);
920 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
921 sigbuffer_add_value (buf, 0);
923 case MONO_TYPE_GENERICINST:
924 encode_generic_class (assembly, type->data.generic_class, buf);
928 sigbuffer_add_value (buf, type->type);
929 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
932 g_error ("need to encode type %x", type->type);
937 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
939 MONO_REQ_GC_UNSAFE_MODE;
941 mono_error_init (error);
944 sigbuffer_add_value (buf, MONO_TYPE_VOID);
948 MonoType *t = mono_reflection_type_get_handle (type, error);
949 return_if_nok (error);
950 encode_type (assembly, t, buf);
954 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
956 MONO_REQ_GC_UNSAFE_MODE;
960 mono_error_init (error);
963 for (i = 0; i < mono_array_length (modreq); ++i) {
964 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
965 return_if_nok (error);
966 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
967 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
971 for (i = 0; i < mono_array_length (modopt); ++i) {
972 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
973 return_if_nok (error);
974 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
975 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
980 #ifndef DISABLE_REFLECTION_EMIT
982 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
984 MONO_REQ_GC_UNSAFE_MODE;
988 guint32 nparams = sig->param_count;
994 sigbuffer_init (&buf, 32);
996 * FIXME: vararg, explicit_this, differenc call_conv values...
998 idx = sig->call_convention;
1000 idx |= 0x20; /* hasthis */
1001 if (sig->generic_param_count)
1002 idx |= 0x10; /* generic */
1003 sigbuffer_add_byte (&buf, idx);
1004 if (sig->generic_param_count)
1005 sigbuffer_add_value (&buf, sig->generic_param_count);
1006 sigbuffer_add_value (&buf, nparams);
1007 encode_type (assembly, sig->ret, &buf);
1008 for (i = 0; i < nparams; ++i) {
1009 if (i == sig->sentinelpos)
1010 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1011 encode_type (assembly, sig->params [i], &buf);
1013 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1014 sigbuffer_free (&buf);
1020 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1022 MONO_REQ_GC_UNSAFE_MODE;
1024 mono_error_init (error);
1027 * FIXME: reuse code from method_encode_signature().
1031 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1032 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1033 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1036 sigbuffer_init (&buf, 32);
1037 /* LAMESPEC: all the call conv spec is foobared */
1038 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1039 if (mb->call_conv & 2)
1040 idx |= 0x5; /* vararg */
1041 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1042 idx |= 0x20; /* hasthis */
1044 idx |= 0x10; /* generic */
1045 sigbuffer_add_byte (&buf, idx);
1047 sigbuffer_add_value (&buf, ngparams);
1048 sigbuffer_add_value (&buf, nparams + notypes);
1049 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1052 encode_reflection_type (assembly, mb->rtype, &buf, error);
1055 for (i = 0; i < nparams; ++i) {
1056 MonoArray *modreq = NULL;
1057 MonoArray *modopt = NULL;
1058 MonoReflectionType *pt;
1060 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1061 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1062 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1063 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1064 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1067 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1068 encode_reflection_type (assembly, pt, &buf, error);
1073 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1074 for (i = 0; i < notypes; ++i) {
1075 MonoReflectionType *pt;
1077 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1078 encode_reflection_type (assembly, pt, &buf, error);
1083 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1085 sigbuffer_free (&buf);
1090 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1092 MONO_REQ_GC_UNSAFE_MODE;
1094 mono_error_init (error);
1096 MonoDynamicTable *table;
1098 guint32 idx, sig_idx;
1099 guint nl = mono_array_length (ilgen->locals);
1103 sigbuffer_init (&buf, 32);
1104 sigbuffer_add_value (&buf, 0x07);
1105 sigbuffer_add_value (&buf, nl);
1106 for (i = 0; i < nl; ++i) {
1107 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1110 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1112 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1113 if (!is_ok (error)) {
1114 sigbuffer_free (&buf);
1118 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1119 sigbuffer_free (&buf);
1121 if (assembly->standalonesig_cache == NULL)
1122 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1123 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1127 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1128 idx = table->next_idx ++;
1130 alloc_table (table, table->rows);
1131 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1133 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1135 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1141 method_count_clauses (MonoReflectionILGen *ilgen)
1143 MONO_REQ_GC_UNSAFE_MODE;
1145 guint32 num_clauses = 0;
1148 MonoILExceptionInfo *ex_info;
1149 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1150 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1151 if (ex_info->handlers)
1152 num_clauses += mono_array_length (ex_info->handlers);
1160 #ifndef DISABLE_REFLECTION_EMIT
1161 static MonoExceptionClause*
1162 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1164 MONO_REQ_GC_UNSAFE_MODE;
1166 mono_error_init (error);
1168 MonoExceptionClause *clauses;
1169 MonoExceptionClause *clause;
1170 MonoILExceptionInfo *ex_info;
1171 MonoILExceptionBlock *ex_block;
1172 guint32 finally_start;
1173 int i, j, clause_index;;
1175 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1178 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1179 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1180 finally_start = ex_info->start + ex_info->len;
1181 if (!ex_info->handlers)
1183 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1184 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1185 clause = &(clauses [clause_index]);
1187 clause->flags = ex_block->type;
1188 clause->try_offset = ex_info->start;
1190 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1191 clause->try_len = finally_start - ex_info->start;
1193 clause->try_len = ex_info->len;
1194 clause->handler_offset = ex_block->start;
1195 clause->handler_len = ex_block->len;
1196 if (ex_block->extype) {
1197 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1199 if (!is_ok (error)) {
1200 image_g_free (image, clauses);
1203 clause->data.catch_class = mono_class_from_mono_type (extype);
1205 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1206 clause->data.filter_offset = ex_block->filter_offset;
1208 clause->data.filter_offset = 0;
1210 finally_start = ex_block->start + ex_block->len;
1218 #endif /* !DISABLE_REFLECTION_EMIT */
1221 * method_encode_code:
1223 * @assembly the assembly
1224 * @mb the managed MethodBuilder
1225 * @error set on error
1227 * Note that the return value is not sensible if @error is set.
1230 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1232 MONO_REQ_GC_UNSAFE_MODE;
1237 gint32 max_stack, i;
1238 gint32 num_locals = 0;
1239 gint32 num_exception = 0;
1242 char fat_header [12];
1244 guint16 short_value;
1245 guint32 local_sig = 0;
1246 guint32 header_size = 12;
1249 mono_error_init (error);
1251 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1252 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1256 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1258 code = mb->ilgen->code;
1259 code_size = mb->ilgen->code_len;
1260 max_stack = mb->ilgen->max_stack;
1261 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1262 if (mb->ilgen->ex_handlers)
1263 num_exception = method_count_clauses (mb->ilgen);
1267 char *name = mono_string_to_utf8 (mb->name);
1268 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1269 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1275 code_size = mono_array_length (code);
1276 max_stack = 8; /* we probably need to run a verifier on the code... */
1279 stream_data_align (&assembly->code);
1281 /* check for exceptions, maxstack, locals */
1282 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1284 if (code_size < 64 && !(code_size & 1)) {
1285 flags = (code_size << 2) | 0x2;
1286 } else if (code_size < 32 && (code_size & 1)) {
1287 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1291 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1292 /* add to the fixup todo list */
1293 if (mb->ilgen && mb->ilgen->num_token_fixups)
1294 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1295 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1296 return assembly->text_rva + idx;
1300 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1301 return_val_if_nok (error, 0);
1304 * FIXME: need to set also the header size in fat_flags.
1305 * (and more sects and init locals flags)
1309 fat_flags |= METHOD_HEADER_MORE_SECTS;
1310 if (mb->init_locals)
1311 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1312 fat_header [0] = fat_flags;
1313 fat_header [1] = (header_size / 4 ) << 4;
1314 short_value = GUINT16_TO_LE (max_stack);
1315 memcpy (fat_header + 2, &short_value, 2);
1316 int_value = GUINT32_TO_LE (code_size);
1317 memcpy (fat_header + 4, &int_value, 4);
1318 int_value = GUINT32_TO_LE (local_sig);
1319 memcpy (fat_header + 8, &int_value, 4);
1320 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1321 /* add to the fixup todo list */
1322 if (mb->ilgen && mb->ilgen->num_token_fixups)
1323 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1325 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1326 if (num_exception) {
1327 unsigned char sheader [4];
1328 MonoILExceptionInfo * ex_info;
1329 MonoILExceptionBlock * ex_block;
1332 stream_data_align (&assembly->code);
1333 /* always use fat format for now */
1334 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1335 num_exception *= 6 * sizeof (guint32);
1336 num_exception += 4; /* include the size of the header */
1337 sheader [1] = num_exception & 0xff;
1338 sheader [2] = (num_exception >> 8) & 0xff;
1339 sheader [3] = (num_exception >> 16) & 0xff;
1340 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1341 /* fat header, so we are already aligned */
1343 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1344 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1345 if (ex_info->handlers) {
1346 int finally_start = ex_info->start + ex_info->len;
1347 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1349 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1351 val = GUINT32_TO_LE (ex_block->type);
1352 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1354 val = GUINT32_TO_LE (ex_info->start);
1355 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1356 /* need fault, too, probably */
1357 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1358 val = GUINT32_TO_LE (finally_start - ex_info->start);
1360 val = GUINT32_TO_LE (ex_info->len);
1361 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362 /* handler offset */
1363 val = GUINT32_TO_LE (ex_block->start);
1364 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1366 val = GUINT32_TO_LE (ex_block->len);
1367 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1368 finally_start = ex_block->start + ex_block->len;
1369 if (ex_block->extype) {
1370 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1371 return_val_if_nok (error, 0);
1373 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1375 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1376 val = ex_block->filter_offset;
1380 val = GUINT32_TO_LE (val);
1381 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1382 /*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",
1383 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);*/
1386 g_error ("No clauses for ex info block %d", i);
1390 return assembly->text_rva + idx;
1394 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1396 MONO_REQ_GC_NEUTRAL_MODE;
1399 MonoDynamicTable *table;
1402 table = &assembly->tables [table_idx];
1404 g_assert (col < table->columns);
1406 values = table->values + table->columns;
1407 for (i = 1; i <= table->rows; ++i) {
1408 if (values [col] == token)
1410 values += table->columns;
1416 * LOCKING: Acquires the loader lock.
1418 static MonoCustomAttrInfo*
1419 lookup_custom_attr (MonoImage *image, gpointer member)
1421 MONO_REQ_GC_NEUTRAL_MODE;
1423 MonoCustomAttrInfo* res;
1425 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1430 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1436 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1438 MONO_REQ_GC_UNSAFE_MODE;
1440 /* FIXME: Need to do more checks */
1441 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1442 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1444 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1451 static MonoCustomAttrInfo*
1452 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1454 MONO_REQ_GC_UNSAFE_MODE;
1456 int i, index, count, not_visible;
1457 MonoCustomAttrInfo *ainfo;
1458 MonoReflectionCustomAttr *cattr;
1462 /* FIXME: check in assembly the Run flag is set */
1464 count = mono_array_length (cattrs);
1466 /* Skip nonpublic attributes since MS.NET seems to do the same */
1467 /* FIXME: This needs to be done more globally */
1469 for (i = 0; i < count; ++i) {
1470 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471 if (!custom_attr_visible (image, cattr))
1474 count -= not_visible;
1476 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1478 ainfo->image = image;
1479 ainfo->num_attrs = count;
1480 ainfo->cached = alloc_img != NULL;
1482 for (i = 0; i < count; ++i) {
1483 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484 if (custom_attr_visible (image, cattr)) {
1485 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1486 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1487 ainfo->attrs [index].ctor = cattr->ctor->method;
1488 ainfo->attrs [index].data = saved;
1489 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1497 #ifndef DISABLE_REFLECTION_EMIT
1499 * LOCKING: Acquires the loader lock.
1502 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1504 MONO_REQ_GC_UNSAFE_MODE;
1506 MonoCustomAttrInfo *ainfo, *tmp;
1508 if (!cattrs || !mono_array_length (cattrs))
1511 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1513 mono_loader_lock ();
1514 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1516 mono_custom_attrs_free (tmp);
1517 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1518 mono_loader_unlock ();
1524 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1526 MONO_REQ_GC_NEUTRAL_MODE;
1528 if (ainfo && !ainfo->cached)
1533 * idx is the table index of the object
1534 * type is one of MONO_CUSTOM_ATTR_*
1537 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1539 MONO_REQ_GC_UNSAFE_MODE;
1541 MonoDynamicTable *table;
1542 MonoReflectionCustomAttr *cattr;
1544 guint32 count, i, token;
1546 char *p = blob_size;
1548 mono_error_init (error);
1550 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1553 count = mono_array_length (cattrs);
1554 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1555 table->rows += count;
1556 alloc_table (table, table->rows);
1557 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1558 idx <<= MONO_CUSTOM_ATTR_BITS;
1560 for (i = 0; i < count; ++i) {
1561 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1562 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1563 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1564 if (!mono_error_ok (error)) goto fail;
1565 type = mono_metadata_token_index (token);
1566 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1567 switch (mono_metadata_token_table (token)) {
1568 case MONO_TABLE_METHOD:
1569 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1571 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1572 * method, not the one returned by mono_image_create_token ().
1574 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1576 case MONO_TABLE_MEMBERREF:
1577 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1580 g_warning ("got wrong token in custom attr");
1583 values [MONO_CUSTOM_ATTR_TYPE] = type;
1585 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1586 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1587 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1588 values += MONO_CUSTOM_ATTR_SIZE;
1599 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1601 MONO_REQ_GC_UNSAFE_MODE;
1603 MonoDynamicTable *table;
1605 guint32 count, i, idx;
1606 MonoReflectionPermissionSet *perm;
1611 count = mono_array_length (permissions);
1612 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1613 table->rows += count;
1614 alloc_table (table, table->rows);
1616 for (i = 0; i < mono_array_length (permissions); ++i) {
1617 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1619 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1621 idx = mono_metadata_token_index (parent_token);
1622 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1623 switch (mono_metadata_token_table (parent_token)) {
1624 case MONO_TABLE_TYPEDEF:
1625 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1627 case MONO_TABLE_METHOD:
1628 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1630 case MONO_TABLE_ASSEMBLY:
1631 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1634 g_assert_not_reached ();
1637 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1638 values [MONO_DECL_SECURITY_PARENT] = idx;
1639 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1646 * Fill in the MethodDef and ParamDef tables for a method.
1647 * This is used for both normal methods and constructors.
1650 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1652 MONO_REQ_GC_UNSAFE_MODE;
1654 MonoDynamicTable *table;
1658 mono_error_init (error);
1660 /* room in this table is already allocated */
1661 table = &assembly->tables [MONO_TABLE_METHOD];
1662 *mb->table_idx = table->next_idx ++;
1663 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1664 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1665 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1666 values [MONO_METHOD_FLAGS] = mb->attrs;
1667 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1668 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1669 return_val_if_nok (error, FALSE);
1670 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1671 return_val_if_nok (error, FALSE);
1673 table = &assembly->tables [MONO_TABLE_PARAM];
1674 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1676 mono_image_add_decl_security (assembly,
1677 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1680 MonoDynamicTable *mtable;
1683 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1684 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1687 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1688 if (mono_array_get (mb->pinfo, gpointer, i))
1691 table->rows += count;
1692 alloc_table (table, table->rows);
1693 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1694 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1695 MonoReflectionParamBuilder *pb;
1696 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1697 values [MONO_PARAM_FLAGS] = pb->attrs;
1698 values [MONO_PARAM_SEQUENCE] = i;
1699 if (pb->name != NULL) {
1700 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1702 values [MONO_PARAM_NAME] = 0;
1704 values += MONO_PARAM_SIZE;
1705 if (pb->marshal_info) {
1707 alloc_table (mtable, mtable->rows);
1708 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1709 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1710 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1711 return_val_if_nok (error, FALSE);
1713 pb->table_idx = table->next_idx++;
1714 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1715 guint32 field_type = 0;
1716 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1718 alloc_table (mtable, mtable->rows);
1719 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1720 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1721 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1722 mvalues [MONO_CONSTANT_TYPE] = field_type;
1723 mvalues [MONO_CONSTANT_PADDING] = 0;
1732 #ifndef DISABLE_REFLECTION_EMIT
1734 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1736 MONO_REQ_GC_UNSAFE_MODE;
1738 mono_error_init (error);
1739 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1741 rmb->ilgen = mb->ilgen;
1742 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1743 return_val_if_nok (error, FALSE);
1744 rmb->parameters = mb->parameters;
1745 rmb->generic_params = mb->generic_params;
1746 rmb->generic_container = mb->generic_container;
1747 rmb->opt_types = NULL;
1748 rmb->pinfo = mb->pinfo;
1749 rmb->attrs = mb->attrs;
1750 rmb->iattrs = mb->iattrs;
1751 rmb->call_conv = mb->call_conv;
1752 rmb->code = mb->code;
1753 rmb->type = mb->type;
1754 rmb->name = mb->name;
1755 rmb->table_idx = &mb->table_idx;
1756 rmb->init_locals = mb->init_locals;
1757 rmb->skip_visibility = FALSE;
1758 rmb->return_modreq = mb->return_modreq;
1759 rmb->return_modopt = mb->return_modopt;
1760 rmb->param_modreq = mb->param_modreq;
1761 rmb->param_modopt = mb->param_modopt;
1762 rmb->permissions = mb->permissions;
1763 rmb->mhandle = mb->mhandle;
1768 rmb->charset = mb->charset;
1769 rmb->extra_flags = mb->extra_flags;
1770 rmb->native_cc = mb->native_cc;
1771 rmb->dllentry = mb->dllentry;
1779 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1781 MONO_REQ_GC_UNSAFE_MODE;
1783 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1785 mono_error_init (error);
1787 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1789 rmb->ilgen = mb->ilgen;
1790 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1791 return_val_if_nok (error, FALSE);
1792 rmb->parameters = mb->parameters;
1793 rmb->generic_params = NULL;
1794 rmb->generic_container = NULL;
1795 rmb->opt_types = NULL;
1796 rmb->pinfo = mb->pinfo;
1797 rmb->attrs = mb->attrs;
1798 rmb->iattrs = mb->iattrs;
1799 rmb->call_conv = mb->call_conv;
1801 rmb->type = mb->type;
1802 rmb->name = mono_string_new (mono_domain_get (), name);
1803 rmb->table_idx = &mb->table_idx;
1804 rmb->init_locals = mb->init_locals;
1805 rmb->skip_visibility = FALSE;
1806 rmb->return_modreq = NULL;
1807 rmb->return_modopt = NULL;
1808 rmb->param_modreq = mb->param_modreq;
1809 rmb->param_modopt = mb->param_modopt;
1810 rmb->permissions = mb->permissions;
1811 rmb->mhandle = mb->mhandle;
1819 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1821 MONO_REQ_GC_UNSAFE_MODE;
1823 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1825 rmb->ilgen = mb->ilgen;
1826 rmb->rtype = mb->rtype;
1827 rmb->parameters = mb->parameters;
1828 rmb->generic_params = NULL;
1829 rmb->generic_container = NULL;
1830 rmb->opt_types = NULL;
1832 rmb->attrs = mb->attrs;
1834 rmb->call_conv = mb->call_conv;
1836 rmb->type = (MonoObject *) mb->owner;
1837 rmb->name = mb->name;
1838 rmb->table_idx = NULL;
1839 rmb->init_locals = mb->init_locals;
1840 rmb->skip_visibility = mb->skip_visibility;
1841 rmb->return_modreq = NULL;
1842 rmb->return_modopt = NULL;
1843 rmb->param_modreq = NULL;
1844 rmb->param_modopt = NULL;
1845 rmb->permissions = NULL;
1846 rmb->mhandle = mb->mhandle;
1853 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1855 MONO_REQ_GC_UNSAFE_MODE;
1857 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1858 MonoDynamicTable *table;
1861 MonoReflectionMethod *m;
1864 mono_error_init (error);
1866 if (!mb->override_methods)
1869 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1870 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1872 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1874 alloc_table (table, table->rows);
1875 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1876 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1877 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1879 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1880 return_val_if_nok (error, FALSE);
1882 switch (mono_metadata_token_table (tok)) {
1883 case MONO_TABLE_MEMBERREF:
1884 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1886 case MONO_TABLE_METHOD:
1887 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1890 g_assert_not_reached ();
1892 values [MONO_METHODIMPL_DECLARATION] = tok;
1898 #ifndef DISABLE_REFLECTION_EMIT
1900 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1902 MONO_REQ_GC_UNSAFE_MODE;
1904 MonoDynamicTable *table;
1906 ReflectionMethodBuilder rmb;
1909 mono_error_init (error);
1911 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1912 !mono_image_basic_method (&rmb, assembly, error))
1915 mb->table_idx = *rmb.table_idx;
1917 if (mb->dll) { /* It's a P/Invoke method */
1919 /* map CharSet values to on-disk values */
1920 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1921 int extra_flags = mb->extra_flags;
1922 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1924 alloc_table (table, table->rows);
1925 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1927 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1928 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1930 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1932 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1933 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1934 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1935 table = &assembly->tables [MONO_TABLE_MODULEREF];
1937 alloc_table (table, table->rows);
1938 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1939 values [MONO_IMPLMAP_SCOPE] = table->rows;
1943 if (mb->generic_params) {
1944 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1945 table->rows += mono_array_length (mb->generic_params);
1946 alloc_table (table, table->rows);
1947 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1948 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1950 mono_image_get_generic_param_info (
1951 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1959 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1961 MONO_REQ_GC_UNSAFE_MODE;
1963 ReflectionMethodBuilder rmb;
1965 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1968 if (!mono_image_basic_method (&rmb, assembly, error))
1971 mb->table_idx = *rmb.table_idx;
1978 type_get_fully_qualified_name (MonoType *type)
1980 MONO_REQ_GC_NEUTRAL_MODE;
1982 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1986 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1988 MONO_REQ_GC_UNSAFE_MODE;
1993 klass = mono_class_from_mono_type (type);
1995 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1996 ta = klass->image->assembly;
1997 if (assembly_is_dynamic (ta) || (ta == ass)) {
1998 if (klass->generic_class || klass->generic_container)
1999 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2000 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2005 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2008 #ifndef DISABLE_REFLECTION_EMIT
2009 /*field_image is the image to which the eventual custom mods have been encoded against*/
2011 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2013 MONO_REQ_GC_NEUTRAL_MODE;
2016 guint32 idx, i, token;
2018 if (!assembly->save)
2021 sigbuffer_init (&buf, 32);
2023 sigbuffer_add_value (&buf, 0x06);
2024 /* encode custom attributes before the type */
2025 if (type->num_mods) {
2026 for (i = 0; i < type->num_mods; ++i) {
2029 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2030 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2032 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2034 token = type->modifiers [i].token;
2037 if (type->modifiers [i].required)
2038 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2040 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2042 sigbuffer_add_value (&buf, token);
2045 encode_type (assembly, type, &buf);
2046 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2047 sigbuffer_free (&buf);
2053 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2055 MONO_REQ_GC_UNSAFE_MODE;
2057 mono_error_init (error);
2061 guint32 typespec = 0;
2065 init_type_builder_generics (fb->type, error);
2066 return_val_if_nok (error, 0);
2068 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2069 return_val_if_nok (error, 0);
2070 klass = mono_class_from_mono_type (type);
2072 sigbuffer_init (&buf, 32);
2074 sigbuffer_add_value (&buf, 0x06);
2075 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2078 /* encode custom attributes before the type */
2080 if (klass->generic_container)
2081 typespec = create_typespec (assembly, type);
2084 MonoGenericClass *gclass;
2085 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2086 encode_generic_class (assembly, gclass, &buf);
2088 encode_type (assembly, type, &buf);
2090 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2091 sigbuffer_free (&buf);
2094 sigbuffer_free (&buf);
2099 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2101 MONO_REQ_GC_UNSAFE_MODE;
2103 char blob_size [64];
2104 char *b = blob_size;
2107 guint32 idx = 0, len = 0, dummy = 0;
2109 buf = (char *)g_malloc (64);
2111 *ret_type = MONO_TYPE_CLASS;
2113 box_val = (char*)&dummy;
2115 box_val = ((char*)val) + sizeof (MonoObject);
2116 *ret_type = val->vtable->klass->byval_arg.type;
2119 switch (*ret_type) {
2120 case MONO_TYPE_BOOLEAN:
2125 case MONO_TYPE_CHAR:
2142 case MONO_TYPE_VALUETYPE: {
2143 MonoClass *klass = val->vtable->klass;
2145 if (klass->enumtype) {
2146 *ret_type = mono_class_enum_basetype (klass)->type;
2148 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2151 g_error ("we can't encode valuetypes, we should have never reached this line");
2154 case MONO_TYPE_CLASS:
2156 case MONO_TYPE_STRING: {
2157 MonoString *str = (MonoString*)val;
2158 /* there is no signature */
2159 len = str->length * 2;
2160 mono_metadata_encode_value (len, b, &b);
2161 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2163 char *swapped = g_malloc (2 * mono_string_length (str));
2164 const char *p = (const char*)mono_string_chars (str);
2166 swap_with_size (swapped, p, 2, mono_string_length (str));
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2171 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2177 case MONO_TYPE_GENERICINST:
2178 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2181 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2184 /* there is no signature */
2185 mono_metadata_encode_value (len, b, &b);
2186 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2187 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2188 swap_with_size (blob_size, box_val, len, 1);
2189 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2191 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2199 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2201 MONO_REQ_GC_UNSAFE_MODE;
2203 mono_error_init (error);
2209 sigbuffer_init (&buf, 32);
2211 sigbuffer_add_value (&buf, minfo->type);
2213 switch (minfo->type) {
2214 case MONO_NATIVE_BYVALTSTR:
2215 case MONO_NATIVE_BYVALARRAY:
2216 sigbuffer_add_value (&buf, minfo->count);
2218 case MONO_NATIVE_LPARRAY:
2219 if (minfo->eltype || minfo->has_size) {
2220 sigbuffer_add_value (&buf, minfo->eltype);
2221 if (minfo->has_size) {
2222 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2223 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2225 /* LAMESPEC: ElemMult is undocumented */
2226 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2230 case MONO_NATIVE_SAFEARRAY:
2232 sigbuffer_add_value (&buf, minfo->eltype);
2234 case MONO_NATIVE_CUSTOM:
2236 str = mono_string_to_utf8 (minfo->guid);
2238 sigbuffer_add_value (&buf, len);
2239 sigbuffer_add_mem (&buf, str, len);
2242 sigbuffer_add_value (&buf, 0);
2244 /* native type name */
2245 sigbuffer_add_value (&buf, 0);
2246 /* custom marshaler type name */
2247 if (minfo->marshaltype || minfo->marshaltyperef) {
2248 if (minfo->marshaltyperef) {
2249 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2250 if (!is_ok (error)) {
2251 sigbuffer_free (&buf);
2254 str = type_get_fully_qualified_name (marshaltype);
2256 str = mono_string_to_utf8 (minfo->marshaltype);
2258 sigbuffer_add_value (&buf, len);
2259 sigbuffer_add_mem (&buf, str, len);
2262 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2263 sigbuffer_add_value (&buf, 0);
2265 if (minfo->mcookie) {
2266 str = mono_string_to_utf8 (minfo->mcookie);
2268 sigbuffer_add_value (&buf, len);
2269 sigbuffer_add_mem (&buf, str, len);
2272 sigbuffer_add_value (&buf, 0);
2278 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2279 sigbuffer_free (&buf);
2284 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2286 MONO_REQ_GC_UNSAFE_MODE;
2288 mono_error_init (error);
2290 MonoDynamicTable *table;
2293 /* maybe this fixup should be done in the C# code */
2294 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2295 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2296 table = &assembly->tables [MONO_TABLE_FIELD];
2297 fb->table_idx = table->next_idx ++;
2298 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2299 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2300 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2301 values [MONO_FIELD_FLAGS] = fb->attrs;
2302 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2303 return_if_nok (error);
2306 if (fb->offset != -1) {
2307 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2309 alloc_table (table, table->rows);
2310 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2311 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2312 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2314 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2315 MonoTypeEnum field_type = (MonoTypeEnum)0;
2316 table = &assembly->tables [MONO_TABLE_CONSTANT];
2318 alloc_table (table, table->rows);
2319 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2320 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2321 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2322 values [MONO_CONSTANT_TYPE] = field_type;
2323 values [MONO_CONSTANT_PADDING] = 0;
2325 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2327 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2329 alloc_table (table, table->rows);
2330 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2331 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2333 * We store it in the code section because it's simpler for now.
2336 if (mono_array_length (fb->rva_data) >= 10)
2337 stream_data_align (&assembly->code);
2338 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2340 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2341 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2343 if (fb->marshal_info) {
2344 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2346 alloc_table (table, table->rows);
2347 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2348 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2349 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2350 return_if_nok (error);
2355 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2357 MONO_REQ_GC_UNSAFE_MODE;
2359 mono_error_init (error);
2362 guint32 nparams = 0;
2363 MonoReflectionMethodBuilder *mb = fb->get_method;
2364 MonoReflectionMethodBuilder *smb = fb->set_method;
2367 if (mb && mb->parameters)
2368 nparams = mono_array_length (mb->parameters);
2369 if (!mb && smb && smb->parameters)
2370 nparams = mono_array_length (smb->parameters) - 1;
2371 sigbuffer_init (&buf, 32);
2372 if (fb->call_conv & 0x20)
2373 sigbuffer_add_byte (&buf, 0x28);
2375 sigbuffer_add_byte (&buf, 0x08);
2376 sigbuffer_add_value (&buf, nparams);
2378 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2381 for (i = 0; i < nparams; ++i) {
2382 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2383 encode_reflection_type (assembly, pt, &buf, error);
2387 } else if (smb && smb->parameters) {
2388 /* the property type is the last param */
2389 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2393 for (i = 0; i < nparams; ++i) {
2394 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2395 encode_reflection_type (assembly, pt, &buf, error);
2400 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2405 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2406 sigbuffer_free (&buf);
2409 sigbuffer_free (&buf);
2414 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2416 MONO_REQ_GC_UNSAFE_MODE;
2418 mono_error_init (error);
2420 MonoDynamicTable *table;
2422 guint num_methods = 0;
2426 * we need to set things in the following tables:
2427 * PROPERTYMAP (info already filled in _get_type_info ())
2428 * PROPERTY (rows already preallocated in _get_type_info ())
2429 * METHOD (method info already done with the generic method code)
2433 table = &assembly->tables [MONO_TABLE_PROPERTY];
2434 pb->table_idx = table->next_idx ++;
2435 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2436 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2437 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2438 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2439 return_if_nok (error);
2442 /* FIXME: we still don't handle 'other' methods */
2443 if (pb->get_method) num_methods ++;
2444 if (pb->set_method) num_methods ++;
2446 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2447 table->rows += num_methods;
2448 alloc_table (table, table->rows);
2450 if (pb->get_method) {
2451 semaidx = table->next_idx ++;
2452 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2453 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2454 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2455 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2457 if (pb->set_method) {
2458 semaidx = table->next_idx ++;
2459 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2460 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2461 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2462 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2464 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2465 MonoTypeEnum field_type = (MonoTypeEnum)0;
2466 table = &assembly->tables [MONO_TABLE_CONSTANT];
2468 alloc_table (table, table->rows);
2469 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2470 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2471 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2472 values [MONO_CONSTANT_TYPE] = field_type;
2473 values [MONO_CONSTANT_PADDING] = 0;
2478 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2480 MONO_REQ_GC_UNSAFE_MODE;
2482 MonoDynamicTable *table;
2484 guint num_methods = 0;
2488 * we need to set things in the following tables:
2489 * EVENTMAP (info already filled in _get_type_info ())
2490 * EVENT (rows already preallocated in _get_type_info ())
2491 * METHOD (method info already done with the generic method code)
2494 table = &assembly->tables [MONO_TABLE_EVENT];
2495 eb->table_idx = table->next_idx ++;
2496 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2497 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2498 values [MONO_EVENT_FLAGS] = eb->attrs;
2499 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2500 return_if_nok (error);
2501 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2504 * FIXME: we still don't handle 'other' methods
2506 if (eb->add_method) num_methods ++;
2507 if (eb->remove_method) num_methods ++;
2508 if (eb->raise_method) num_methods ++;
2510 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2511 table->rows += num_methods;
2512 alloc_table (table, table->rows);
2514 if (eb->add_method) {
2515 semaidx = table->next_idx ++;
2516 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2517 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2518 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2519 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2521 if (eb->remove_method) {
2522 semaidx = table->next_idx ++;
2523 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2524 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2525 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2526 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2528 if (eb->raise_method) {
2529 semaidx = table->next_idx ++;
2530 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2531 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2532 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2533 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2538 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2540 MONO_REQ_GC_UNSAFE_MODE;
2542 mono_error_init (error);
2544 MonoDynamicTable *table;
2545 guint32 num_constraints, i;
2549 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2550 num_constraints = gparam->iface_constraints ?
2551 mono_array_length (gparam->iface_constraints) : 0;
2552 table->rows += num_constraints;
2553 if (gparam->base_type)
2555 alloc_table (table, table->rows);
2557 if (gparam->base_type) {
2558 table_idx = table->next_idx ++;
2559 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2561 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2562 return_if_nok (error);
2563 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2564 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2567 for (i = 0; i < num_constraints; i++) {
2568 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2569 gparam->iface_constraints, gpointer, i);
2571 table_idx = table->next_idx ++;
2572 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2574 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2575 return_if_nok (error);
2577 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2578 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2583 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2585 MONO_REQ_GC_UNSAFE_MODE;
2587 GenericParamTableEntry *entry;
2590 * The GenericParam table must be sorted according to the `owner' field.
2591 * We need to do this sorting prior to writing the GenericParamConstraint
2592 * table, since we have to use the final GenericParam table indices there
2593 * and they must also be sorted.
2596 entry = g_new0 (GenericParamTableEntry, 1);
2597 entry->owner = owner;
2598 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2599 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2600 entry->gparam = gparam;
2602 g_ptr_array_add (assembly->gen_params, entry);
2606 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2608 MONO_REQ_GC_UNSAFE_MODE;
2610 MonoDynamicTable *table;
2611 MonoGenericParam *param;
2615 mono_error_init (error);
2617 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2618 table_idx = table->next_idx ++;
2619 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2621 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2622 return_val_if_nok (error, FALSE);
2624 param = gparam_type->data.generic_param;
2626 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2627 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2628 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2629 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2631 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2634 encode_constraints (entry->gparam, table_idx, assembly, error);
2635 return_val_if_nok (error, FALSE);
2641 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2643 MONO_REQ_GC_UNSAFE_MODE;
2645 MonoDynamicTable *table;
2648 guint32 cols [MONO_ASSEMBLY_SIZE];
2652 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2655 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2656 table = &assembly->tables [MONO_TABLE_MODULEREF];
2657 token = table->next_idx ++;
2659 alloc_table (table, table->rows);
2660 values = table->values + token * MONO_MODULEREF_SIZE;
2661 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2663 token <<= MONO_RESOLUTION_SCOPE_BITS;
2664 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2665 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2670 if (assembly_is_dynamic (image->assembly))
2672 memset (cols, 0, sizeof (cols));
2674 /* image->assembly->image is the manifest module */
2675 image = image->assembly->image;
2676 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2679 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2680 token = table->next_idx ++;
2682 alloc_table (table, table->rows);
2683 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2684 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2685 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2686 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2687 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2688 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2689 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2690 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2691 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2693 if (strcmp ("", image->assembly->aname.culture)) {
2694 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2695 image->assembly->aname.culture);
2698 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2699 guchar pubtoken [9];
2701 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2702 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2704 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2706 token <<= MONO_RESOLUTION_SCOPE_BITS;
2707 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2708 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2713 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2715 MONO_REQ_GC_NEUTRAL_MODE;
2717 MonoDynamicTable *table;
2722 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2725 sigbuffer_init (&buf, 32);
2726 switch (type->type) {
2727 case MONO_TYPE_FNPTR:
2729 case MONO_TYPE_SZARRAY:
2730 case MONO_TYPE_ARRAY:
2732 case MONO_TYPE_MVAR:
2733 case MONO_TYPE_GENERICINST:
2734 encode_type (assembly, type, &buf);
2736 case MONO_TYPE_CLASS:
2737 case MONO_TYPE_VALUETYPE: {
2738 MonoClass *k = mono_class_from_mono_type (type);
2739 if (!k || !k->generic_container) {
2740 sigbuffer_free (&buf);
2743 encode_type (assembly, type, &buf);
2747 sigbuffer_free (&buf);
2751 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2752 if (assembly->save) {
2753 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2754 alloc_table (table, table->rows + 1);
2755 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2756 values [MONO_TYPESPEC_SIGNATURE] = token;
2758 sigbuffer_free (&buf);
2760 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2761 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2767 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2769 MONO_REQ_GC_UNSAFE_MODE;
2771 MonoDynamicTable *table;
2773 guint32 token, scope, enclosing;
2776 /* if the type requires a typespec, we must try that first*/
2777 if (try_typespec && (token = create_typespec (assembly, type)))
2779 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2782 klass = mono_class_from_mono_type (type);
2784 klass = mono_class_from_mono_type (type);
2787 * If it's in the same module and not a generic type parameter:
2789 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2790 (type->type != MONO_TYPE_MVAR)) {
2791 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2792 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2793 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2797 if (klass->nested_in) {
2798 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2799 /* get the typeref idx of the enclosing type */
2800 enclosing >>= MONO_TYPEDEFORREF_BITS;
2801 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2803 scope = resolution_scope_from_image (assembly, klass->image);
2805 table = &assembly->tables [MONO_TABLE_TYPEREF];
2806 if (assembly->save) {
2807 alloc_table (table, table->rows + 1);
2808 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2809 values [MONO_TYPEREF_SCOPE] = scope;
2810 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2811 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2813 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2814 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2816 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2821 * Despite the name, we handle also TypeSpec (with the above helper).
2824 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2826 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2829 #ifndef DISABLE_REFLECTION_EMIT
2831 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2833 MONO_REQ_GC_NEUTRAL_MODE;
2835 MonoDynamicTable *table;
2837 guint32 token, pclass;
2839 switch (parent & MONO_TYPEDEFORREF_MASK) {
2840 case MONO_TYPEDEFORREF_TYPEREF:
2841 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2843 case MONO_TYPEDEFORREF_TYPESPEC:
2844 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2846 case MONO_TYPEDEFORREF_TYPEDEF:
2847 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2850 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2853 /* extract the index */
2854 parent >>= MONO_TYPEDEFORREF_BITS;
2856 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2858 if (assembly->save) {
2859 alloc_table (table, table->rows + 1);
2860 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2861 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2862 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2863 values [MONO_MEMBERREF_SIGNATURE] = sig;
2866 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2873 * Insert a memberef row into the metadata: the token that point to the memberref
2874 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2875 * mono_image_get_fieldref_token()).
2876 * The sig param is an index to an already built signature.
2879 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2881 MONO_REQ_GC_NEUTRAL_MODE;
2883 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2884 return mono_image_add_memberef_row (assembly, parent, name, sig);
2889 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2891 MONO_REQ_GC_NEUTRAL_MODE;
2894 MonoMethodSignature *sig;
2896 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2898 if (create_typespec) {
2899 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2904 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2905 if (token && !create_typespec)
2908 g_assert (!method->is_inflated);
2911 * A methodref signature can't contain an unmanaged calling convention.
2913 sig = mono_metadata_signature_dup (mono_method_signature (method));
2914 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2915 sig->call_convention = MONO_CALL_DEFAULT;
2916 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2917 method->name, method_encode_signature (assembly, sig));
2919 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2922 if (create_typespec) {
2923 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2924 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2925 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2927 if (assembly->save) {
2930 alloc_table (table, table->rows + 1);
2931 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2932 values [MONO_METHODSPEC_METHOD] = token;
2933 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2936 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2938 /*methodspec and memberef tokens are diferent, */
2939 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2946 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2948 guint32 token, parent, sig;
2949 ReflectionMethodBuilder rmb;
2950 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2952 mono_error_init (error);
2953 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2957 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2961 * A methodref signature can't contain an unmanaged calling convention.
2962 * Since some flags are encoded as part of call_conv, we need to check against it.
2964 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2965 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2967 sig = method_builder_encode_signature (assembly, &rmb, error);
2968 return_val_if_nok (error, 0);
2970 if (tb->generic_params) {
2971 parent = create_generic_typespec (assembly, tb, error);
2972 return_val_if_nok (error, 0);
2974 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2975 return_val_if_nok (error, 0);
2977 parent = mono_image_typedef_or_ref (assembly, t);
2980 char *name = mono_string_to_utf8 (method->name);
2982 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2985 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2991 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2992 const gchar *name, guint32 sig)
2994 MonoDynamicTable *table;
2998 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3000 if (assembly->save) {
3001 alloc_table (table, table->rows + 1);
3002 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3003 values [MONO_MEMBERREF_CLASS] = original;
3004 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3005 values [MONO_MEMBERREF_SIGNATURE] = sig;
3008 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3015 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3019 guint32 nparams = mono_array_length (mb->generic_params);
3022 if (!assembly->save)
3025 sigbuffer_init (&buf, 32);
3027 sigbuffer_add_value (&buf, 0xa);
3028 sigbuffer_add_value (&buf, nparams);
3030 for (i = 0; i < nparams; i++) {
3031 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3032 sigbuffer_add_value (&buf, i);
3035 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3036 sigbuffer_free (&buf);
3041 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3043 MonoDynamicTable *table;
3045 guint32 token, mtoken = 0;
3047 mono_error_init (error);
3048 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3052 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3054 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3055 if (!mono_error_ok (error))
3058 switch (mono_metadata_token_table (mtoken)) {
3059 case MONO_TABLE_MEMBERREF:
3060 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3062 case MONO_TABLE_METHOD:
3063 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3066 g_assert_not_reached ();
3069 if (assembly->save) {
3070 alloc_table (table, table->rows + 1);
3071 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3072 values [MONO_METHODSPEC_METHOD] = mtoken;
3073 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3076 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3079 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3084 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3088 mono_error_init (error);
3090 if (mb->generic_params && create_methodspec)
3091 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3093 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3097 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3098 if (!mono_error_ok (error))
3100 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3105 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3107 guint32 token, parent, sig;
3108 ReflectionMethodBuilder rmb;
3110 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3112 mono_error_init (error);
3114 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3118 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3121 if (tb->generic_params) {
3122 parent = create_generic_typespec (assembly, tb, error);
3123 return_val_if_nok (error, 0);
3125 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3126 return_val_if_nok (error, 0);
3127 parent = mono_image_typedef_or_ref (assembly, type);
3130 name = mono_string_to_utf8 (rmb.name);
3131 sig = method_builder_encode_signature (assembly, &rmb, error);
3132 return_val_if_nok (error, 0);
3134 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3137 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3143 is_field_on_inst (MonoClassField *field)
3145 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3149 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3152 get_field_on_inst_generic_type (MonoClassField *field)
3154 MonoClass *klass, *gtd;
3155 MonoDynamicGenericClass *dgclass;
3158 g_assert (is_field_on_inst (field));
3160 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3162 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3163 field_index = field - dgclass->fields;
3164 return dgclass->field_generic_types [field_index];
3167 klass = field->parent;
3168 gtd = klass->generic_class->container_class;
3170 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3171 field_index = field - klass->fields;
3172 return gtd->fields [field_index].type;
3175 g_assert_not_reached ();
3179 #ifndef DISABLE_REFLECTION_EMIT
3181 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3187 g_assert (field->parent);
3189 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3193 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3194 int index = field - field->parent->fields;
3195 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3197 if (is_field_on_inst (field))
3198 type = get_field_on_inst_generic_type (field);
3200 type = mono_field_get_type (field);
3202 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3203 mono_field_get_name (field),
3204 fieldref_encode_signature (assembly, field->parent->image, type));
3205 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3210 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3214 MonoGenericClass *gclass;
3218 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3221 if (is_sre_field_builder (mono_object_class (f->fb))) {
3222 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3223 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3224 return_val_if_nok (error, 0);
3225 klass = mono_class_from_mono_type (type);
3226 gclass = type->data.generic_class;
3227 g_assert (gclass->is_dynamic);
3229 guint32 sig_token = field_encode_signature (assembly, fb, error);
3230 return_val_if_nok (error, 0);
3231 name = mono_string_to_utf8 (fb->name);
3232 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3234 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3236 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3238 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3239 return_val_if_nok (error, 0);
3240 klass = mono_class_from_mono_type (type);
3242 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3243 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3245 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3246 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3249 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3254 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3258 MonoGenericClass *gclass;
3261 mono_error_init (error);
3263 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3265 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3269 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3270 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3271 ReflectionMethodBuilder rmb;
3274 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3275 return_val_if_nok (error, 0);
3276 klass = mono_class_from_mono_type (type);
3278 gclass = type->data.generic_class;
3279 g_assert (gclass->is_dynamic);
3281 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3284 sig = method_builder_encode_signature (assembly, &rmb, error);
3285 return_val_if_nok (error, 0);
3287 name = mono_string_to_utf8 (rmb.name);
3289 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3291 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3292 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3294 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3295 return_val_if_nok (error, 0);
3296 klass = mono_class_from_mono_type (type);
3298 sig = method_encode_signature (assembly, mono_method_signature (mm));
3299 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3301 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3302 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3306 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3311 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3314 MonoGenericContext tmp_context;
3315 MonoType **type_argv;
3316 MonoGenericInst *ginst;
3317 MonoMethod *method, *inflated;
3320 mono_error_init (error);
3322 init_type_builder_generics ((MonoObject*)m->inst, error);
3323 return_val_if_nok (error, NULL);
3325 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3326 return_val_if_nok (error, NULL);
3328 klass = method->klass;
3330 if (m->method_args == NULL)
3333 if (method->is_inflated)
3334 method = ((MonoMethodInflated *) method)->declaring;
3336 count = mono_array_length (m->method_args);
3338 type_argv = g_new0 (MonoType *, count);
3339 for (i = 0; i < count; i++) {
3340 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3341 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3342 return_val_if_nok (error, NULL);
3344 ginst = mono_metadata_get_generic_inst (count, type_argv);
3347 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3348 tmp_context.method_inst = ginst;
3350 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3351 mono_error_assert_ok (error);
3356 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3358 guint32 sig, token = 0;
3362 mono_error_init (error);
3364 if (m->method_args) {
3365 MonoMethod *inflated;
3367 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3368 return_val_if_nok (error, 0);
3370 if (create_methodspec)
3371 token = mono_image_get_methodspec_token (assembly, inflated);
3373 token = mono_image_get_inflated_method_token (assembly, inflated);
3377 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3381 if (is_sre_method_builder (mono_object_class (m->mb))) {
3382 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3383 MonoGenericClass *gclass;
3384 ReflectionMethodBuilder rmb;
3387 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3388 return_val_if_nok (error, 0);
3389 klass = mono_class_from_mono_type (type);
3390 gclass = type->data.generic_class;
3391 g_assert (gclass->is_dynamic);
3393 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3396 sig = method_builder_encode_signature (assembly, &rmb, error);
3397 return_val_if_nok (error, 0);
3399 name = mono_string_to_utf8 (rmb.name);
3401 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3403 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3404 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3406 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3407 return_val_if_nok (error, 0);
3408 klass = mono_class_from_mono_type (type);
3410 sig = method_encode_signature (assembly, mono_method_signature (mm));
3411 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3413 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3414 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3417 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3422 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3426 guint32 nparams = context->method_inst->type_argc;
3429 if (!assembly->save)
3432 sigbuffer_init (&buf, 32);
3434 * FIXME: vararg, explicit_this, differenc call_conv values...
3436 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3437 sigbuffer_add_value (&buf, nparams);
3439 for (i = 0; i < nparams; i++)
3440 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3442 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3443 sigbuffer_free (&buf);
3448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3450 MonoDynamicTable *table;
3452 guint32 token, mtoken = 0, sig;
3453 MonoMethodInflated *imethod;
3454 MonoMethod *declaring;
3456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3458 g_assert (method->is_inflated);
3459 imethod = (MonoMethodInflated *) method;
3460 declaring = imethod->declaring;
3462 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3463 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3465 if (!mono_method_signature (declaring)->generic_param_count)
3468 switch (mono_metadata_token_table (mtoken)) {
3469 case MONO_TABLE_MEMBERREF:
3470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3472 case MONO_TABLE_METHOD:
3473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3476 g_assert_not_reached ();
3479 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3481 if (assembly->save) {
3482 alloc_table (table, table->rows + 1);
3483 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3484 values [MONO_METHODSPEC_METHOD] = mtoken;
3485 values [MONO_METHODSPEC_SIGNATURE] = sig;
3488 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3497 MonoMethodInflated *imethod;
3500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3504 g_assert (method->is_inflated);
3505 imethod = (MonoMethodInflated *) method;
3507 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3508 token = method_encode_methodspec (assembly, method);
3510 guint32 sig = method_encode_signature (
3511 assembly, mono_method_signature (imethod->declaring));
3512 token = mono_image_get_memberref_token (
3513 assembly, &method->klass->byval_arg, method->name, sig);
3516 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3523 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3526 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3527 token = mono_image_get_memberref_token (
3528 assembly, &m->klass->byval_arg, m->name, sig);
3534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3536 MonoDynamicTable *table;
3545 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3546 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3547 * Because of this, we must not insert it into the `typeref' hash table.
3549 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3550 return_val_if_nok (error, 0);
3551 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3555 sigbuffer_init (&buf, 32);
3557 g_assert (tb->generic_params);
3558 klass = mono_class_from_mono_type (type);
3560 if (tb->generic_container) {
3561 if (!mono_reflection_create_generic_class (tb, error))
3565 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3566 g_assert (klass->generic_container);
3567 sigbuffer_add_value (&buf, klass->byval_arg.type);
3568 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3570 count = mono_array_length (tb->generic_params);
3571 sigbuffer_add_value (&buf, count);
3572 for (i = 0; i < count; i++) {
3573 MonoReflectionGenericParam *gparam;
3575 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3576 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3580 encode_type (assembly, gparam_type, &buf);
3583 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3585 if (assembly->save) {
3586 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3587 alloc_table (table, table->rows + 1);
3588 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3589 values [MONO_TYPESPEC_SIGNATURE] = token;
3591 sigbuffer_free (&buf);
3593 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3594 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3598 sigbuffer_free (&buf);
3603 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3606 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3608 int i, count, len, pos;
3611 mono_error_init (error);
3615 count += mono_array_length (modreq);
3617 count += mono_array_length (modopt);
3620 return mono_metadata_type_dup (NULL, type);
3622 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3623 t = (MonoType *)g_malloc (len);
3624 memcpy (t, type, MONO_SIZEOF_TYPE);
3626 t->num_mods = count;
3629 for (i = 0; i < mono_array_length (modreq); ++i) {
3630 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3633 t->modifiers [pos].required = 1;
3634 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3639 for (i = 0; i < mono_array_length (modopt); ++i) {
3640 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3643 t->modifiers [pos].required = 0;
3644 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3656 init_type_builder_generics (MonoObject *type, MonoError *error)
3658 MonoReflectionTypeBuilder *tb;
3660 mono_error_init (error);
3662 if (!is_sre_type_builder(mono_object_class (type)))
3664 tb = (MonoReflectionTypeBuilder *)type;
3666 if (tb && tb->generic_container)
3667 mono_reflection_create_generic_class (tb, error);
3671 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3673 MonoDynamicTable *table;
3674 MonoType *custom = NULL, *type;
3676 guint32 token, pclass, parent, sig;
3679 mono_error_init (error);
3681 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3685 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3686 return_val_if_nok (error, 0);
3687 /* FIXME: is this call necessary? */
3688 mono_class_from_mono_type (typeb);
3690 /*FIXME this is one more layer of ugliness due how types are created.*/
3691 init_type_builder_generics (fb->type, error);
3692 return_val_if_nok (error, 0);
3694 /* fb->type does not include the custom modifiers */
3695 /* FIXME: We should do this in one place when a fieldbuilder is created */
3696 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3697 return_val_if_nok (error, 0);
3699 if (fb->modreq || fb->modopt) {
3700 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3701 return_val_if_nok (error, 0);
3704 sig = fieldref_encode_signature (assembly, NULL, type);
3707 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3708 return_val_if_nok (error, 0);
3709 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3711 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3712 parent >>= MONO_TYPEDEFORREF_BITS;
3714 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3716 name = mono_string_to_utf8 (fb->name);
3718 if (assembly->save) {
3719 alloc_table (table, table->rows + 1);
3720 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3721 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3722 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3723 values [MONO_MEMBERREF_SIGNATURE] = sig;
3726 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3728 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3734 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3740 mono_error_init (error);
3742 if (!assembly->save)
3745 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3746 g_assert (helper->type == 2);
3748 if (helper->arguments)
3749 nargs = mono_array_length (helper->arguments);
3753 sigbuffer_init (&buf, 32);
3755 /* Encode calling convention */
3756 /* Change Any to Standard */
3757 if ((helper->call_conv & 0x03) == 0x03)
3758 helper->call_conv = 0x01;
3759 /* explicit_this implies has_this */
3760 if (helper->call_conv & 0x40)
3761 helper->call_conv &= 0x20;
3763 if (helper->call_conv == 0) { /* Unmanaged */
3764 idx = helper->unmanaged_call_conv - 1;
3767 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3768 if (helper->call_conv & 0x02) /* varargs */
3772 sigbuffer_add_byte (&buf, idx);
3773 sigbuffer_add_value (&buf, nargs);
3774 encode_reflection_type (assembly, helper->return_type, &buf, error);
3777 for (i = 0; i < nargs; ++i) {
3778 MonoArray *modreqs = NULL;
3779 MonoArray *modopts = NULL;
3780 MonoReflectionType *pt;
3782 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3783 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3784 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3785 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3787 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3790 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3791 encode_reflection_type (assembly, pt, &buf, error);
3795 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3796 sigbuffer_free (&buf);
3800 sigbuffer_free (&buf);
3805 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3808 MonoDynamicTable *table;
3811 mono_error_init (error);
3813 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3814 idx = table->next_idx ++;
3816 alloc_table (table, table->rows);
3817 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3819 values [MONO_STAND_ALONE_SIGNATURE] =
3820 mono_reflection_encode_sighelper (assembly, helper, error);
3821 return_val_if_nok (error, 0);
3827 reflection_cc_to_file (int call_conv) {
3828 switch (call_conv & 0x3) {
3830 case 1: return MONO_CALL_DEFAULT;
3831 case 2: return MONO_CALL_VARARG;
3833 g_assert_not_reached ();
3837 #endif /* !DISABLE_REFLECTION_EMIT */
3841 MonoMethodSignature *sig;
3846 #ifndef DISABLE_REFLECTION_EMIT
3848 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3853 MonoMethodSignature *sig;
3854 ArrayMethod *am = NULL;
3857 mono_error_init (error);
3859 nparams = mono_array_length (m->parameters);
3860 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3862 sig->sentinelpos = -1;
3863 sig->call_convention = reflection_cc_to_file (m->call_conv);
3864 sig->param_count = nparams;
3866 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3870 sig->ret = &mono_defaults.void_class->byval_arg;
3872 mtype = mono_reflection_type_get_handle (m->parent, error);
3876 for (i = 0; i < nparams; ++i) {
3877 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3882 name = mono_string_to_utf8 (m->name);
3883 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3884 am = (ArrayMethod *)tmp->data;
3885 if (strcmp (name, am->name) == 0 &&
3886 mono_metadata_type_equal (am->parent, mtype) &&
3887 mono_metadata_signature_equal (am->sig, sig)) {
3890 m->table_idx = am->token & 0xffffff;
3894 am = g_new0 (ArrayMethod, 1);
3898 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3899 method_encode_signature (assembly, sig));
3900 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3901 m->table_idx = am->token & 0xffffff;
3912 * Insert into the metadata tables all the info about the TypeBuilder tb.
3913 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3916 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3918 MonoDynamicTable *table;
3920 int i, is_object = 0, is_system = 0;
3923 mono_error_init (error);
3925 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3926 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3927 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3928 n = mono_string_to_utf8 (tb->name);
3929 if (strcmp (n, "Object") == 0)
3931 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3933 n = mono_string_to_utf8 (tb->nspace);
3934 if (strcmp (n, "System") == 0)
3936 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3938 if (tb->parent && !(is_system && is_object) &&
3939 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3940 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3941 return_val_if_nok (error, FALSE);
3942 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3944 values [MONO_TYPEDEF_EXTENDS] = 0;
3946 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3947 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3950 * if we have explicitlayout or sequentiallayouts, output data in the
3951 * ClassLayout table.
3953 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3954 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3955 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3957 alloc_table (table, table->rows);
3958 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3959 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3960 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3961 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3964 /* handle interfaces */
3965 if (tb->interfaces) {
3966 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3968 table->rows += mono_array_length (tb->interfaces);
3969 alloc_table (table, table->rows);
3970 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3971 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3972 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3973 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3974 return_val_if_nok (error, FALSE);
3975 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3976 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3977 values += MONO_INTERFACEIMPL_SIZE;
3983 table = &assembly->tables [MONO_TABLE_FIELD];
3984 table->rows += tb->num_fields;
3985 alloc_table (table, table->rows);
3986 for (i = 0; i < tb->num_fields; ++i) {
3987 mono_image_get_field_info (
3988 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3989 return_val_if_nok (error, FALSE);
3993 /* handle constructors */
3995 table = &assembly->tables [MONO_TABLE_METHOD];
3996 table->rows += mono_array_length (tb->ctors);
3997 alloc_table (table, table->rows);
3998 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3999 if (!mono_image_get_ctor_info (domain,
4000 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4006 /* handle methods */
4008 table = &assembly->tables [MONO_TABLE_METHOD];
4009 table->rows += tb->num_methods;
4010 alloc_table (table, table->rows);
4011 for (i = 0; i < tb->num_methods; ++i) {
4012 if (!mono_image_get_method_info (
4013 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4018 /* Do the same with properties etc.. */
4019 if (tb->events && mono_array_length (tb->events)) {
4020 table = &assembly->tables [MONO_TABLE_EVENT];
4021 table->rows += mono_array_length (tb->events);
4022 alloc_table (table, table->rows);
4023 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4025 alloc_table (table, table->rows);
4026 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4027 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4028 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4029 for (i = 0; i < mono_array_length (tb->events); ++i) {
4030 mono_image_get_event_info (
4031 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4032 return_val_if_nok (error, FALSE);
4035 if (tb->properties && mono_array_length (tb->properties)) {
4036 table = &assembly->tables [MONO_TABLE_PROPERTY];
4037 table->rows += mono_array_length (tb->properties);
4038 alloc_table (table, table->rows);
4039 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4041 alloc_table (table, table->rows);
4042 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4043 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4044 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4045 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4046 mono_image_get_property_info (
4047 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4048 return_val_if_nok (error, FALSE);
4052 /* handle generic parameters */
4053 if (tb->generic_params) {
4054 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4055 table->rows += mono_array_length (tb->generic_params);
4056 alloc_table (table, table->rows);
4057 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4058 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4060 mono_image_get_generic_param_info (
4061 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4065 mono_image_add_decl_security (assembly,
4066 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4069 MonoDynamicTable *ntable;
4071 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4072 ntable->rows += mono_array_length (tb->subtypes);
4073 alloc_table (ntable, ntable->rows);
4074 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4076 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4077 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4079 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4080 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4081 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4082 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4083 mono_string_to_utf8 (tb->name), tb->table_idx,
4084 ntable->next_idx, ntable->rows);*/
4085 values += MONO_NESTED_CLASS_SIZE;
4095 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4099 mono_ptr_array_append (*types, type);
4101 if (!type->subtypes)
4104 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4105 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4106 collect_types (types, subtype);
4111 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4113 if ((*type1)->table_idx < (*type2)->table_idx)
4116 if ((*type1)->table_idx > (*type2)->table_idx)
4123 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4126 mono_error_init (error);
4129 for (i = 0; i < mono_array_length (pinfo); ++i) {
4130 MonoReflectionParamBuilder *pb;
4131 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4134 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4142 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4145 mono_error_init (error);
4147 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4150 for (i = 0; i < tb->num_fields; ++i) {
4151 MonoReflectionFieldBuilder* fb;
4152 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4153 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4158 for (i = 0; i < mono_array_length (tb->events); ++i) {
4159 MonoReflectionEventBuilder* eb;
4160 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4161 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4165 if (tb->properties) {
4166 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4167 MonoReflectionPropertyBuilder* pb;
4168 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4169 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4174 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4175 MonoReflectionCtorBuilder* cb;
4176 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4177 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4178 !params_add_cattrs (assembly, cb->pinfo, error))
4184 for (i = 0; i < tb->num_methods; ++i) {
4185 MonoReflectionMethodBuilder* mb;
4186 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4187 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4188 !params_add_cattrs (assembly, mb->pinfo, error))
4194 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4195 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4204 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4208 mono_error_init (error);
4210 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4213 if (moduleb->global_methods) {
4214 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4215 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4216 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4217 !params_add_cattrs (assembly, mb->pinfo, error))
4222 if (moduleb->global_fields) {
4223 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4224 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4225 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4230 if (moduleb->types) {
4231 for (i = 0; i < moduleb->num_types; ++i) {
4232 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4241 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4243 MonoDynamicTable *table;
4247 char *b = blob_size;
4250 table = &assembly->tables [MONO_TABLE_FILE];
4252 alloc_table (table, table->rows);
4253 values = table->values + table->next_idx * MONO_FILE_SIZE;
4254 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4255 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4256 if (image_is_dynamic (module->image)) {
4257 /* This depends on the fact that the main module is emitted last */
4258 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4259 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4262 path = g_strdup (module->image->name);
4264 mono_sha1_get_digest_from_file (path, hash);
4267 mono_metadata_encode_value (20, b, &b);
4268 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4269 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4274 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4276 MonoDynamicTable *table;
4279 table = &assembly->tables [MONO_TABLE_MODULE];
4280 mb->table_idx = table->next_idx ++;
4281 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4282 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4285 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4286 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4287 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4288 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4292 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4293 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4295 MonoDynamicTable *table;
4299 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4300 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4303 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4305 alloc_table (table, table->rows);
4306 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4308 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4309 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4310 if (klass->nested_in)
4311 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4313 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4314 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4315 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4317 res = table->next_idx;
4321 /* Emit nested types */
4322 if (klass->ext && klass->ext->nested_classes) {
4325 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4326 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4333 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4334 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4340 mono_error_init (error);
4342 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4343 return_if_nok (error);
4345 klass = mono_class_from_mono_type (t);
4347 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4349 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4350 parent_index, assembly);
4354 * We need to do this ourselves since klass->nested_classes is not set up.
4357 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4358 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4359 return_if_nok (error);
4365 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4366 guint32 module_index, MonoDynamicImage *assembly)
4368 MonoImage *image = module->image;
4372 t = &image->tables [MONO_TABLE_TYPEDEF];
4374 for (i = 0; i < t->rows; ++i) {
4376 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4377 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4379 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4380 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4385 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4387 MonoDynamicTable *table;
4389 guint32 scope, scope_idx, impl, current_idx;
4390 gboolean forwarder = TRUE;
4391 gpointer iter = NULL;
4394 if (klass->nested_in) {
4395 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4398 scope = resolution_scope_from_image (assembly, klass->image);
4399 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4400 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4401 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4404 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4407 alloc_table (table, table->rows);
4408 current_idx = table->next_idx;
4409 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4411 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4412 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4413 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4414 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4415 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4419 while ((nested = mono_class_get_nested_types (klass, &iter)))
4420 add_exported_type (assemblyb, assembly, nested, current_idx);
4424 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4430 if (!assemblyb->type_forwarders)
4433 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4434 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4439 type = mono_reflection_type_get_handle (t, &error);
4440 mono_error_assert_ok (&error);
4443 klass = mono_class_from_mono_type (type);
4445 add_exported_type (assemblyb, assembly, klass, 0);
4449 #define align_pointer(base,p)\
4451 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4453 (p) += 4 - (__diff & 3);\
4457 compare_constants (const void *a, const void *b)
4459 const guint32 *a_values = (const guint32 *)a;
4460 const guint32 *b_values = (const guint32 *)b;
4461 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4465 compare_semantics (const void *a, const void *b)
4467 const guint32 *a_values = (const guint32 *)a;
4468 const guint32 *b_values = (const guint32 *)b;
4469 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4472 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4476 compare_custom_attrs (const void *a, const void *b)
4478 const guint32 *a_values = (const guint32 *)a;
4479 const guint32 *b_values = (const guint32 *)b;
4481 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4485 compare_field_marshal (const void *a, const void *b)
4487 const guint32 *a_values = (const guint32 *)a;
4488 const guint32 *b_values = (const guint32 *)b;
4490 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4494 compare_nested (const void *a, const void *b)
4496 const guint32 *a_values = (const guint32 *)a;
4497 const guint32 *b_values = (const guint32 *)b;
4499 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4503 compare_genericparam (const void *a, const void *b)
4506 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4507 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4509 if ((*b_entry)->owner == (*a_entry)->owner) {
4510 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4511 mono_error_assert_ok (&error);
4512 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4513 mono_error_assert_ok (&error);
4515 mono_type_get_generic_param_num (a_type) -
4516 mono_type_get_generic_param_num (b_type);
4518 return (*a_entry)->owner - (*b_entry)->owner;
4522 compare_declsecurity_attrs (const void *a, const void *b)
4524 const guint32 *a_values = (const guint32 *)a;
4525 const guint32 *b_values = (const guint32 *)b;
4527 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4531 compare_interface_impl (const void *a, const void *b)
4533 const guint32 *a_values = (const guint32 *)a;
4534 const guint32 *b_values = (const guint32 *)b;
4536 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4540 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4544 pad_heap (MonoDynamicStream *sh)
4546 if (sh->index & 3) {
4547 int sz = 4 - (sh->index & 3);
4548 memset (sh->data + sh->index, 0, sz);
4555 MonoDynamicStream *stream;
4559 * build_compressed_metadata() fills in the blob of data that represents the
4560 * raw metadata as it will be saved in the PE file. The five streams are output
4561 * and the metadata tables are comnpressed from the guint32 array representation,
4562 * to the compressed on-disk format.
4565 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4567 MonoDynamicTable *table;
4569 guint64 valid_mask = 0;
4570 guint64 sorted_mask;
4571 guint32 heapt_size = 0;
4572 guint32 meta_size = 256; /* allow for header and other stuff */
4573 guint32 table_offset;
4574 guint32 ntables = 0;
4580 struct StreamDesc stream_desc [5];
4582 mono_error_init (error);
4584 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4585 for (i = 0; i < assembly->gen_params->len; i++) {
4586 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4587 if (!write_generic_param_entry (assembly, entry, error))
4591 stream_desc [0].name = "#~";
4592 stream_desc [0].stream = &assembly->tstream;
4593 stream_desc [1].name = "#Strings";
4594 stream_desc [1].stream = &assembly->sheap;
4595 stream_desc [2].name = "#US";
4596 stream_desc [2].stream = &assembly->us;
4597 stream_desc [3].name = "#Blob";
4598 stream_desc [3].stream = &assembly->blob;
4599 stream_desc [4].name = "#GUID";
4600 stream_desc [4].stream = &assembly->guid;
4602 /* tables that are sorted */
4603 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4604 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4605 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4606 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4607 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4608 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4609 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4611 /* Compute table sizes */
4612 /* the MonoImage has already been created in mono_image_basic_init() */
4613 meta = &assembly->image;
4615 /* sizes should be multiple of 4 */
4616 pad_heap (&assembly->blob);
4617 pad_heap (&assembly->guid);
4618 pad_heap (&assembly->sheap);
4619 pad_heap (&assembly->us);
4621 /* Setup the info used by compute_sizes () */
4622 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4623 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4624 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4626 meta_size += assembly->blob.index;
4627 meta_size += assembly->guid.index;
4628 meta_size += assembly->sheap.index;
4629 meta_size += assembly->us.index;
4631 for (i=0; i < MONO_TABLE_NUM; ++i)
4632 meta->tables [i].rows = assembly->tables [i].rows;
4634 for (i = 0; i < MONO_TABLE_NUM; i++){
4635 if (meta->tables [i].rows == 0)
4637 valid_mask |= (guint64)1 << i;
4639 meta->tables [i].row_size = mono_metadata_compute_size (
4640 meta, i, &meta->tables [i].size_bitfield);
4641 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4643 heapt_size += 24; /* #~ header size */
4644 heapt_size += ntables * 4;
4645 /* make multiple of 4 */
4648 meta_size += heapt_size;
4649 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4650 p = (unsigned char*)meta->raw_metadata;
4651 /* the metadata signature */
4652 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4653 /* version numbers and 4 bytes reserved */
4654 int16val = (guint16*)p;
4655 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4656 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4658 /* version string */
4659 int32val = (guint32*)p;
4660 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4662 memcpy (p, meta->version, strlen (meta->version));
4663 p += GUINT32_FROM_LE (*int32val);
4664 align_pointer (meta->raw_metadata, p);
4665 int16val = (guint16*)p;
4666 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4667 *int16val = GUINT16_TO_LE (5); /* number of streams */
4671 * write the stream info.
4673 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4674 table_offset += 3; table_offset &= ~3;
4676 assembly->tstream.index = heapt_size;
4677 for (i = 0; i < 5; ++i) {
4678 int32val = (guint32*)p;
4679 stream_desc [i].stream->offset = table_offset;
4680 *int32val++ = GUINT32_TO_LE (table_offset);
4681 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4682 table_offset += GUINT32_FROM_LE (*int32val);
4683 table_offset += 3; table_offset &= ~3;
4685 strcpy ((char*)p, stream_desc [i].name);
4686 p += strlen (stream_desc [i].name) + 1;
4687 align_pointer (meta->raw_metadata, p);
4690 * now copy the data, the table stream header and contents goes first.
4692 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4693 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4694 int32val = (guint32*)p;
4695 *int32val = GUINT32_TO_LE (0); /* reserved */
4698 *p++ = 2; /* version */
4701 if (meta->idx_string_wide)
4703 if (meta->idx_guid_wide)
4705 if (meta->idx_blob_wide)
4708 *p++ = 1; /* reserved */
4709 int64val = (guint64*)p;
4710 *int64val++ = GUINT64_TO_LE (valid_mask);
4711 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4713 int32val = (guint32*)p;
4714 for (i = 0; i < MONO_TABLE_NUM; i++){
4715 if (meta->tables [i].rows == 0)
4717 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4719 p = (unsigned char*)int32val;
4721 /* sort the tables that still need sorting */
4722 table = &assembly->tables [MONO_TABLE_CONSTANT];
4724 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4725 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4727 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4728 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4730 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4731 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4733 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4734 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4736 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4737 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4738 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4740 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4741 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4743 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4745 /* compress the tables */
4746 for (i = 0; i < MONO_TABLE_NUM; i++){
4749 guint32 bitfield = meta->tables [i].size_bitfield;
4750 if (!meta->tables [i].rows)
4752 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4753 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4754 meta->tables [i].base = (char*)p;
4755 for (row = 1; row <= meta->tables [i].rows; ++row) {
4756 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4757 for (col = 0; col < assembly->tables [i].columns; ++col) {
4758 switch (mono_metadata_table_size (bitfield, col)) {
4760 *p++ = values [col];
4763 *p++ = values [col] & 0xff;
4764 *p++ = (values [col] >> 8) & 0xff;
4767 *p++ = values [col] & 0xff;
4768 *p++ = (values [col] >> 8) & 0xff;
4769 *p++ = (values [col] >> 16) & 0xff;
4770 *p++ = (values [col] >> 24) & 0xff;
4773 g_assert_not_reached ();
4777 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4780 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4781 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4782 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4783 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4784 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4786 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4792 * Some tables in metadata need to be sorted according to some criteria, but
4793 * when methods and fields are first created with reflection, they may be assigned a token
4794 * that doesn't correspond to the final token they will get assigned after the sorting.
4795 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4796 * with the reflection objects that represent them. Once all the tables are set up, the
4797 * reflection objects will contains the correct table index. fixup_method() will fixup the
4798 * tokens for the method with ILGenerator @ilgen.
4801 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4803 guint32 code_idx = GPOINTER_TO_UINT (value);
4804 MonoReflectionILTokenInfo *iltoken;
4805 MonoReflectionFieldBuilder *field;
4806 MonoReflectionCtorBuilder *ctor;
4807 MonoReflectionMethodBuilder *method;
4808 MonoReflectionTypeBuilder *tb;
4809 MonoReflectionArrayMethod *am;
4811 unsigned char *target;
4813 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4814 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4815 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4816 switch (target [3]) {
4817 case MONO_TABLE_FIELD:
4818 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4819 field = (MonoReflectionFieldBuilder *)iltoken->member;
4820 idx = field->table_idx;
4821 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4822 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4823 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4825 g_assert_not_reached ();
4828 case MONO_TABLE_METHOD:
4829 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4830 method = (MonoReflectionMethodBuilder *)iltoken->member;
4831 idx = method->table_idx;
4832 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4833 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4834 idx = ctor->table_idx;
4835 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4836 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4837 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4838 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4840 g_assert_not_reached ();
4843 case MONO_TABLE_TYPEDEF:
4844 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4845 g_assert_not_reached ();
4846 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4847 idx = tb->table_idx;
4849 case MONO_TABLE_MEMBERREF:
4850 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4851 am = (MonoReflectionArrayMethod*)iltoken->member;
4852 idx = am->table_idx;
4853 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4854 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4855 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4856 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4857 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4858 g_assert (m->klass->generic_class || m->klass->generic_container);
4860 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4862 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4863 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4864 g_assert (is_field_on_inst (f));
4866 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4867 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4869 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4871 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4873 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4876 g_assert_not_reached ();
4879 case MONO_TABLE_METHODSPEC:
4880 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4881 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4882 g_assert (mono_method_signature (m)->generic_param_count);
4884 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4886 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4889 g_assert_not_reached ();
4893 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4895 target [0] = idx & 0xff;
4896 target [1] = (idx >> 8) & 0xff;
4897 target [2] = (idx >> 16) & 0xff;
4904 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4905 * value is not known when the table is emitted.
4908 fixup_cattrs (MonoDynamicImage *assembly)
4910 MonoDynamicTable *table;
4912 guint32 type, i, idx, token;
4915 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4917 for (i = 0; i < table->rows; ++i) {
4918 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4920 type = values [MONO_CUSTOM_ATTR_TYPE];
4921 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4922 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4923 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4924 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4927 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4928 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4929 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4930 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4931 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4932 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4933 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4934 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4941 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4943 MonoDynamicTable *table;
4946 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4948 alloc_table (table, table->rows);
4949 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4950 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4951 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4952 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4953 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4958 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4960 MonoDynamicTable *table;
4964 char *b = blob_size;
4966 guint32 idx, offset;
4968 if (rsrc->filename) {
4969 name = mono_string_to_utf8 (rsrc->filename);
4970 sname = g_path_get_basename (name);
4972 table = &assembly->tables [MONO_TABLE_FILE];
4974 alloc_table (table, table->rows);
4975 values = table->values + table->next_idx * MONO_FILE_SIZE;
4976 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4977 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4980 mono_sha1_get_digest_from_file (name, hash);
4981 mono_metadata_encode_value (20, b, &b);
4982 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4983 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4985 idx = table->next_idx++;
4987 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4993 data = mono_array_addr (rsrc->data, char, 0);
4994 len = mono_array_length (rsrc->data);
5000 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5001 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5002 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5003 mono_image_add_stream_data (&assembly->resources, data, len);
5007 * The entry should be emitted into the MANIFESTRESOURCE table of
5008 * the main module, but that needs to reference the FILE table
5009 * which isn't emitted yet.
5016 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5020 set_version_from_string (MonoString *version, guint32 *values)
5022 gchar *ver, *p, *str;
5025 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5026 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5027 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5028 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5031 ver = str = mono_string_to_utf8 (version);
5032 for (i = 0; i < 4; ++i) {
5033 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5039 /* handle Revision and Build */
5049 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5053 char *b = blob_size;
5058 len = mono_array_length (pkey);
5059 mono_metadata_encode_value (len, b, &b);
5060 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5061 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5063 assembly->public_key = (guint8 *)g_malloc (len);
5064 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5065 assembly->public_key_len = len;
5067 /* Special case: check for ECMA key (16 bytes) */
5068 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5069 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5070 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5071 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5072 /* minimum key size (in 2.0) is 384 bits */
5073 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5075 /* FIXME - verifier */
5076 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5077 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5079 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5085 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5087 MonoDynamicTable *table;
5088 MonoDynamicImage *assembly;
5089 MonoReflectionAssemblyBuilder *assemblyb;
5093 guint32 module_index;
5095 mono_error_init (error);
5097 assemblyb = moduleb->assemblyb;
5098 assembly = moduleb->dynamic_image;
5099 domain = mono_object_domain (assemblyb);
5101 /* Emit ASSEMBLY table */
5102 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5103 alloc_table (table, 1);
5104 values = table->values + MONO_ASSEMBLY_SIZE;
5105 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5106 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5107 if (assemblyb->culture) {
5108 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5110 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5112 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5113 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5114 set_version_from_string (assemblyb->version, values);
5116 /* Emit FILE + EXPORTED_TYPE table */
5118 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5120 MonoReflectionModuleBuilder *file_module =
5121 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5122 if (file_module != moduleb) {
5123 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5125 if (file_module->types) {
5126 for (j = 0; j < file_module->num_types; ++j) {
5127 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5128 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5129 return_if_nok (error);
5134 if (assemblyb->loaded_modules) {
5135 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5136 MonoReflectionModule *file_module =
5137 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5138 mono_image_fill_file_table (domain, file_module, assembly);
5140 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5143 if (assemblyb->type_forwarders)
5144 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5146 /* Emit MANIFESTRESOURCE table */
5148 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5150 MonoReflectionModuleBuilder *file_module =
5151 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5152 /* The table for the main module is emitted later */
5153 if (file_module != moduleb) {
5155 if (file_module->resources) {
5156 int len = mono_array_length (file_module->resources);
5157 for (j = 0; j < len; ++j) {
5158 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5159 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5166 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5169 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5170 * for the modulebuilder @moduleb.
5171 * At the end of the process, method and field tokens are fixed up and the
5172 * on-disk compressed metadata representation is created.
5173 * Return TRUE on success, or FALSE on failure and sets @error
5176 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5178 MonoDynamicTable *table;
5179 MonoDynamicImage *assembly;
5180 MonoReflectionAssemblyBuilder *assemblyb;
5186 mono_error_init (error);
5188 assemblyb = moduleb->assemblyb;
5189 assembly = moduleb->dynamic_image;
5190 domain = mono_object_domain (assemblyb);
5192 if (assembly->text_rva)
5195 assembly->text_rva = START_TEXT_RVA;
5197 if (moduleb->is_main) {
5198 mono_image_emit_manifest (moduleb, error);
5199 return_val_if_nok (error, FALSE);
5202 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5203 table->rows = 1; /* .<Module> */
5205 alloc_table (table, table->rows);
5207 * Set the first entry.
5209 values = table->values + table->columns;
5210 values [MONO_TYPEDEF_FLAGS] = 0;
5211 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5212 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5213 values [MONO_TYPEDEF_EXTENDS] = 0;
5214 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5215 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5218 * handle global methods
5219 * FIXME: test what to do when global methods are defined in multiple modules.
5221 if (moduleb->global_methods) {
5222 table = &assembly->tables [MONO_TABLE_METHOD];
5223 table->rows += mono_array_length (moduleb->global_methods);
5224 alloc_table (table, table->rows);
5225 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5226 if (!mono_image_get_method_info (
5227 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5231 if (moduleb->global_fields) {
5232 table = &assembly->tables [MONO_TABLE_FIELD];
5233 table->rows += mono_array_length (moduleb->global_fields);
5234 alloc_table (table, table->rows);
5235 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5236 mono_image_get_field_info (
5237 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5244 table = &assembly->tables [MONO_TABLE_MODULE];
5245 alloc_table (table, 1);
5246 mono_image_fill_module_table (domain, moduleb, assembly);
5248 /* Collect all types into a list sorted by their table_idx */
5249 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5252 for (i = 0; i < moduleb->num_types; ++i) {
5253 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5254 collect_types (&types, type);
5257 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5258 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5259 table->rows += mono_ptr_array_size (types);
5260 alloc_table (table, table->rows);
5263 * Emit type names + namespaces at one place inside the string heap,
5264 * so load_class_names () needs to touch fewer pages.
5266 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5267 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5268 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5270 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5271 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5272 string_heap_insert_mstring (&assembly->sheap, tb->name);
5275 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5276 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5277 if (!mono_image_get_type_info (domain, type, assembly, error))
5282 * table->rows is already set above and in mono_image_fill_module_table.
5284 /* add all the custom attributes at the end, once all the indexes are stable */
5285 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5288 /* CAS assembly permissions */
5289 if (assemblyb->permissions_minimum)
5290 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5291 if (assemblyb->permissions_optional)
5292 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5293 if (assemblyb->permissions_refused)
5294 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5296 if (!module_add_cattrs (assembly, moduleb, error))
5300 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5302 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5303 * the final tokens and don't need another fixup pass. */
5305 if (moduleb->global_methods) {
5306 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5307 MonoReflectionMethodBuilder *mb = mono_array_get (
5308 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5309 if (!mono_image_add_methodimpl (assembly, mb, error))
5314 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5315 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5316 if (type->methods) {
5317 for (j = 0; j < type->num_methods; ++j) {
5318 MonoReflectionMethodBuilder *mb = mono_array_get (
5319 type->methods, MonoReflectionMethodBuilder*, j);
5321 if (!mono_image_add_methodimpl (assembly, mb, error))
5327 fixup_cattrs (assembly);
5330 mono_ptr_array_destroy (types);
5333 return mono_error_ok (error);
5336 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5339 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5341 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5344 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5348 guint32 import_lookup_table;
5352 guint32 import_address_table_rva;
5360 #ifndef DISABLE_REFLECTION_EMIT
5363 * mono_image_insert_string:
5364 * @module: module builder object
5367 * Insert @str into the user string stream of @module.
5370 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5372 MonoDynamicImage *assembly;
5377 if (!module->dynamic_image)
5378 mono_image_module_basic_init (module);
5380 assembly = module->dynamic_image;
5382 if (assembly->save) {
5383 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5384 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5385 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5387 char *swapped = g_malloc (2 * mono_string_length (str));
5388 const char *p = (const char*)mono_string_chars (str);
5390 swap_with_size (swapped, p, 2, mono_string_length (str));
5391 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5395 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5397 mono_image_add_stream_data (&assembly->us, "", 1);
5399 idx = assembly->us.index ++;
5402 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5404 return MONO_TOKEN_STRING | idx;
5408 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5412 MonoMethodSignature *sig;
5414 mono_error_init (error);
5416 klass = obj->vtable->klass;
5417 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5418 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5419 MonoMethodSignature *old;
5420 guint32 sig_token, parent;
5423 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5425 nargs = mono_array_length (opt_param_types);
5426 old = mono_method_signature (method);
5427 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5429 sig->hasthis = old->hasthis;
5430 sig->explicit_this = old->explicit_this;
5431 sig->call_convention = old->call_convention;
5432 sig->generic_param_count = old->generic_param_count;
5433 sig->param_count = old->param_count + nargs;
5434 sig->sentinelpos = old->param_count;
5435 sig->ret = old->ret;
5437 for (i = 0; i < old->param_count; i++)
5438 sig->params [i] = old->params [i];
5440 for (i = 0; i < nargs; i++) {
5441 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5442 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5443 if (!is_ok (error)) goto fail;
5446 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5447 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5448 parent >>= MONO_TYPEDEFORREF_BITS;
5450 parent <<= MONO_MEMBERREF_PARENT_BITS;
5451 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5453 sig_token = method_encode_signature (assembly, sig);
5454 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5455 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5456 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5457 ReflectionMethodBuilder rmb;
5458 guint32 parent, sig_token;
5459 int nopt_args, nparams, ngparams, i;
5461 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5464 rmb.opt_types = opt_param_types;
5465 nopt_args = mono_array_length (opt_param_types);
5467 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5468 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5469 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5471 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5472 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5473 sig->call_convention = rmb.call_conv;
5474 sig->generic_param_count = ngparams;
5475 sig->param_count = nparams + nopt_args;
5476 sig->sentinelpos = nparams;
5477 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5478 if (!is_ok (error)) goto fail;
5480 for (i = 0; i < nparams; i++) {
5481 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5482 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5483 if (!is_ok (error)) goto fail;
5486 for (i = 0; i < nopt_args; i++) {
5487 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5488 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5489 if (!is_ok (error)) goto fail;
5492 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5496 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5497 if (!mono_error_ok (error))
5499 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5501 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5502 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5504 char *name = mono_string_to_utf8 (rmb.name);
5505 token = mono_image_get_varargs_method_token (
5506 assembly, parent, name, sig_token);
5509 g_error ("requested method token for %s\n", klass->name);
5512 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5513 register_dyn_token (assembly, token, obj);
5516 g_assert (!mono_error_ok (error));
5521 * mono_image_create_token:
5522 * @assembly: a dynamic assembly
5524 * @register_token: Whenever to register the token in the assembly->tokens hash.
5526 * Get a token to insert in the IL code stream for the given MemberInfo.
5527 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5528 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5532 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5533 gboolean create_open_instance, gboolean register_token,
5539 mono_error_init (error);
5541 klass = obj->vtable->klass;
5543 /* Check for user defined reflection objects */
5544 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5545 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5546 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5550 if (strcmp (klass->name, "MethodBuilder") == 0) {
5551 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5552 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5554 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5555 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5557 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5558 if (!mono_error_ok (error))
5561 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5562 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5563 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5564 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5566 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5567 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5569 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5570 if (!mono_error_ok (error))
5573 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5574 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5575 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5576 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5577 if (tb->generic_params) {
5578 token = mono_image_get_generic_field_token (assembly, fb, error);
5579 return_val_if_nok (error, 0);
5581 if (tb->module->dynamic_image == assembly) {
5582 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5584 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5587 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5588 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5589 if (create_open_instance && tb->generic_params) {
5591 init_type_builder_generics (obj, error);
5592 return_val_if_nok (error, 0);
5593 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594 return_val_if_nok (error, 0);
5595 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5596 token = mono_metadata_token_from_dor (token);
5597 } else if (tb->module->dynamic_image == assembly) {
5598 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5601 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5602 return_val_if_nok (error, 0);
5603 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5605 } else if (strcmp (klass->name, "MonoType") == 0) {
5606 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5607 return_val_if_nok (error, 0);
5608 MonoClass *mc = mono_class_from_mono_type (type);
5609 token = mono_metadata_token_from_dor (
5610 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5611 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5612 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5613 return_val_if_nok (error, 0);
5614 token = mono_metadata_token_from_dor (
5615 mono_image_typedef_or_ref (assembly, type));
5616 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5617 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5618 return_val_if_nok (error, 0);
5619 token = mono_metadata_token_from_dor (
5620 mono_image_typedef_or_ref (assembly, type));
5621 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5622 strcmp (klass->name, "MonoMethod") == 0 ||
5623 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5624 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5625 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5626 if (m->method->is_inflated) {
5627 if (create_open_instance)
5628 token = mono_image_get_methodspec_token (assembly, m->method);
5630 token = mono_image_get_inflated_method_token (assembly, m->method);
5631 } else if ((m->method->klass->image == &assembly->image) &&
5632 !m->method->klass->generic_class) {
5633 static guint32 method_table_idx = 0xffffff;
5634 if (m->method->klass->wastypebuilder) {
5635 /* we use the same token as the one that was assigned
5636 * to the Methodbuilder.
5637 * FIXME: do the equivalent for Fields.
5639 token = m->method->token;
5642 * Each token should have a unique index, but the indexes are
5643 * assigned by managed code, so we don't know about them. An
5644 * easy solution is to count backwards...
5646 method_table_idx --;
5647 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5650 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5652 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5653 } else if (strcmp (klass->name, "MonoField") == 0) {
5654 MonoReflectionField *f = (MonoReflectionField *)obj;
5655 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5656 static guint32 field_table_idx = 0xffffff;
5658 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5660 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5662 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5663 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5664 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5665 token = mono_image_get_array_token (assembly, m, error);
5666 return_val_if_nok (error, 0);
5667 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5668 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5669 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5670 return_val_if_nok (error, 0);
5671 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5672 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5673 return_val_if_nok (error, 0);
5674 token = mono_metadata_token_from_dor (
5675 mono_image_typedef_or_ref (assembly, type));
5676 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5677 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5678 token = mono_image_get_field_on_inst_token (assembly, f, error);
5679 return_val_if_nok (error, 0);
5680 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5681 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5682 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5683 if (!mono_error_ok (error))
5685 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5686 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5687 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5688 if (!mono_error_ok (error))
5690 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5691 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5692 return_val_if_nok (error, 0);
5693 token = mono_metadata_token_from_dor (
5694 mono_image_typedef_or_ref (assembly, type));
5696 g_error ("requested token for %s\n", klass->name);
5700 mono_image_register_token (assembly, token, obj);
5706 * mono_image_register_token:
5708 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5709 * the Module.ResolveXXXToken () methods to work.
5712 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5716 dynamic_image_lock (assembly);
5717 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5719 /* There could be multiple MethodInfo objects with the same token */
5720 //g_assert (prev == obj);
5722 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5724 dynamic_image_unlock (assembly);
5727 static MonoDynamicImage*
5728 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5730 static const guchar entrycode [16] = {0xff, 0x25, 0};
5731 MonoDynamicImage *image;
5734 const char *version;
5736 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5737 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5739 version = mono_get_runtime_info ()->runtime_version;
5742 /* The MonoGHashTable's need GC tracking */
5743 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5745 image = g_new0 (MonoDynamicImage, 1);
5748 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5750 /*g_print ("created image %p\n", image);*/
5751 /* keep in sync with image.c */
5752 image->image.name = assembly_name;
5753 image->image.assembly_name = image->image.name; /* they may be different */
5754 image->image.module_name = module_name;
5755 image->image.version = g_strdup (version);
5756 image->image.md_version_major = 1;
5757 image->image.md_version_minor = 1;
5758 image->image.dynamic = TRUE;
5760 image->image.references = g_new0 (MonoAssembly*, 1);
5761 image->image.references [0] = NULL;
5763 mono_image_init (&image->image);
5765 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");
5766 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5767 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5768 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5769 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5770 image->handleref = g_hash_table_new (NULL, NULL);
5771 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");
5772 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5773 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");
5774 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");
5775 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5776 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5777 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5778 image->gen_params = g_ptr_array_new ();
5779 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5781 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5782 string_heap_init (&image->sheap);
5783 mono_image_add_stream_data (&image->us, "", 1);
5784 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5785 /* import tables... */
5786 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5787 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5788 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5789 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5790 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5791 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5792 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5793 stream_data_align (&image->code);
5795 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5797 for (i=0; i < MONO_TABLE_NUM; ++i) {
5798 image->tables [i].next_idx = 1;
5799 image->tables [i].columns = table_sizes [i];
5802 image->image.assembly = (MonoAssembly*)assembly;
5803 image->run = assembly->run;
5804 image->save = assembly->save;
5805 image->pe_kind = 0x1; /* ILOnly */
5806 image->machine = 0x14c; /* I386 */
5808 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5810 dynamic_images_lock ();
5812 if (!dynamic_images)
5813 dynamic_images = g_ptr_array_new ();
5815 g_ptr_array_add (dynamic_images, image);
5817 dynamic_images_unlock ();
5824 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5830 release_hashtable (MonoGHashTable **hash)
5833 mono_g_hash_table_destroy (*hash);
5839 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5841 release_hashtable (&image->token_fixups);
5842 release_hashtable (&image->handleref_managed);
5843 release_hashtable (&image->tokens);
5844 release_hashtable (&image->remapped_tokens);
5845 release_hashtable (&image->generic_def_objects);
5846 release_hashtable (&image->methodspec);
5849 // Free dynamic image pass one: Free resources but not image itself
5851 mono_dynamic_image_free (MonoDynamicImage *image)
5853 MonoDynamicImage *di = image;
5858 mono_g_hash_table_destroy (di->methodspec);
5860 g_hash_table_destroy (di->typespec);
5862 g_hash_table_destroy (di->typeref);
5864 g_hash_table_destroy (di->handleref);
5865 if (di->handleref_managed)
5866 mono_g_hash_table_destroy (di->handleref_managed);
5868 mono_g_hash_table_destroy (di->tokens);
5869 if (di->remapped_tokens)
5870 mono_g_hash_table_destroy (di->remapped_tokens);
5871 if (di->generic_def_objects)
5872 mono_g_hash_table_destroy (di->generic_def_objects);
5873 if (di->blob_cache) {
5874 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5875 g_hash_table_destroy (di->blob_cache);
5877 if (di->standalonesig_cache)
5878 g_hash_table_destroy (di->standalonesig_cache);
5879 for (list = di->array_methods; list; list = list->next) {
5880 ArrayMethod *am = (ArrayMethod *)list->data;
5885 g_list_free (di->array_methods);
5886 if (di->gen_params) {
5887 for (i = 0; i < di->gen_params->len; i++) {
5888 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5889 mono_gc_deregister_root ((char*) &entry->gparam);
5892 g_ptr_array_free (di->gen_params, TRUE);
5894 if (di->token_fixups)
5895 mono_g_hash_table_destroy (di->token_fixups);
5896 if (di->method_to_table_idx)
5897 g_hash_table_destroy (di->method_to_table_idx);
5898 if (di->field_to_table_idx)
5899 g_hash_table_destroy (di->field_to_table_idx);
5900 if (di->method_aux_hash)
5901 g_hash_table_destroy (di->method_aux_hash);
5902 if (di->vararg_aux_hash)
5903 g_hash_table_destroy (di->vararg_aux_hash);
5904 g_free (di->strong_name);
5905 g_free (di->win32_res);
5907 g_free (di->public_key);
5909 /*g_print ("string heap destroy for image %p\n", di);*/
5910 mono_dynamic_stream_reset (&di->sheap);
5911 mono_dynamic_stream_reset (&di->code);
5912 mono_dynamic_stream_reset (&di->resources);
5913 mono_dynamic_stream_reset (&di->us);
5914 mono_dynamic_stream_reset (&di->blob);
5915 mono_dynamic_stream_reset (&di->tstream);
5916 mono_dynamic_stream_reset (&di->guid);
5917 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5918 g_free (di->tables [i].values);
5921 dynamic_images_lock ();
5924 g_ptr_array_remove (dynamic_images, di);
5926 dynamic_images_unlock ();
5929 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5931 mono_dynamic_image_free_image (MonoDynamicImage *image)
5933 /* See create_dynamic_mono_image () */
5935 /* Allocated using GC_MALLOC */
5941 #ifndef DISABLE_REFLECTION_EMIT
5944 * mono_image_basic_init:
5945 * @assembly: an assembly builder object
5947 * Create the MonoImage that represents the assembly builder and setup some
5948 * of the helper hash table and the basic metadata streams.
5951 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5953 MonoDynamicAssembly *assembly;
5954 MonoDynamicImage *image;
5955 MonoDomain *domain = mono_object_domain (assemblyb);
5957 if (assemblyb->dynamic_assembly)
5961 /* assembly->assembly.image might be GC allocated */
5962 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5964 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5967 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5969 assembly->assembly.ref_count = 1;
5970 assembly->assembly.dynamic = TRUE;
5971 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5972 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5973 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5974 if (assemblyb->culture)
5975 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5977 assembly->assembly.aname.culture = g_strdup ("");
5979 if (assemblyb->version) {
5980 char *vstr = mono_string_to_utf8 (assemblyb->version);
5981 char **version = g_strsplit (vstr, ".", 4);
5982 char **parts = version;
5983 assembly->assembly.aname.major = atoi (*parts++);
5984 assembly->assembly.aname.minor = atoi (*parts++);
5985 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5986 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5988 g_strfreev (version);
5991 assembly->assembly.aname.major = 0;
5992 assembly->assembly.aname.minor = 0;
5993 assembly->assembly.aname.build = 0;
5994 assembly->assembly.aname.revision = 0;
5997 assembly->run = assemblyb->access != 2;
5998 assembly->save = assemblyb->access != 1;
5999 assembly->domain = domain;
6001 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
6002 image->initial_image = TRUE;
6003 assembly->assembly.aname.name = image->image.name;
6004 assembly->assembly.image = &image->image;
6005 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6006 /* -1 to correct for the trailing NULL byte */
6007 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6008 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6010 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6013 mono_domain_assemblies_lock (domain);
6014 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6015 mono_domain_assemblies_unlock (domain);
6017 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6019 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6021 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6024 #endif /* !DISABLE_REFLECTION_EMIT */
6026 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6029 calc_section_size (MonoDynamicImage *assembly)
6033 /* alignment constraints */
6034 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6035 g_assert ((assembly->code.index % 4) == 0);
6036 assembly->meta_size += 3;
6037 assembly->meta_size &= ~3;
6038 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6039 g_assert ((assembly->resources.index % 4) == 0);
6041 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6042 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6045 if (assembly->win32_res) {
6046 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6048 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6049 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6053 assembly->sections [MONO_SECTION_RELOC].size = 12;
6054 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6064 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6068 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6070 ResTreeNode *t1 = (ResTreeNode*)a;
6071 ResTreeNode *t2 = (ResTreeNode*)b;
6073 return t1->id - t2->id;
6077 * resource_tree_create:
6079 * Organize the resources into a resource tree.
6081 static ResTreeNode *
6082 resource_tree_create (MonoArray *win32_resources)
6084 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6088 tree = g_new0 (ResTreeNode, 1);
6090 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6091 MonoReflectionWin32Resource *win32_res =
6092 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6096 /* FIXME: BUG: this stores managed references in unmanaged memory */
6097 lang_node = g_new0 (ResTreeNode, 1);
6098 lang_node->id = win32_res->lang_id;
6099 lang_node->win32_res = win32_res;
6101 /* Create type node if neccesary */
6103 for (l = tree->children; l; l = l->next)
6104 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6105 type_node = (ResTreeNode*)l->data;
6110 type_node = g_new0 (ResTreeNode, 1);
6111 type_node->id = win32_res->res_type;
6114 * The resource types have to be sorted otherwise
6115 * Windows Explorer can't display the version information.
6117 tree->children = g_slist_insert_sorted (tree->children,
6118 type_node, resource_tree_compare_by_id);
6121 /* Create res node if neccesary */
6123 for (l = type_node->children; l; l = l->next)
6124 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6125 res_node = (ResTreeNode*)l->data;
6130 res_node = g_new0 (ResTreeNode, 1);
6131 res_node->id = win32_res->res_id;
6132 type_node->children = g_slist_append (type_node->children, res_node);
6135 res_node->children = g_slist_append (res_node->children, lang_node);
6142 * resource_tree_encode:
6144 * Encode the resource tree into the format used in the PE file.
6147 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6150 MonoPEResourceDir dir;
6151 MonoPEResourceDirEntry dir_entry;
6152 MonoPEResourceDataEntry data_entry;
6154 guint32 res_id_entries;
6157 * For the format of the resource directory, see the article
6158 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6162 memset (&dir, 0, sizeof (dir));
6163 memset (&dir_entry, 0, sizeof (dir_entry));
6164 memset (&data_entry, 0, sizeof (data_entry));
6166 g_assert (sizeof (dir) == 16);
6167 g_assert (sizeof (dir_entry) == 8);
6168 g_assert (sizeof (data_entry) == 16);
6170 node->offset = p - begin;
6172 /* IMAGE_RESOURCE_DIRECTORY */
6173 res_id_entries = g_slist_length (node->children);
6174 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6176 memcpy (p, &dir, sizeof (dir));
6179 /* Reserve space for entries */
6181 p += sizeof (dir_entry) * res_id_entries;
6183 /* Write children */
6184 for (l = node->children; l; l = l->next) {
6185 ResTreeNode *child = (ResTreeNode*)l->data;
6187 if (child->win32_res) {
6190 child->offset = p - begin;
6192 /* IMAGE_RESOURCE_DATA_ENTRY */
6193 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6194 size = mono_array_length (child->win32_res->res_data);
6195 data_entry.rde_size = GUINT32_TO_LE (size);
6197 memcpy (p, &data_entry, sizeof (data_entry));
6198 p += sizeof (data_entry);
6200 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6203 resource_tree_encode (child, begin, p, &p);
6207 /* IMAGE_RESOURCE_ENTRY */
6208 for (l = node->children; l; l = l->next) {
6209 ResTreeNode *child = (ResTreeNode*)l->data;
6211 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6212 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6214 memcpy (entries, &dir_entry, sizeof (dir_entry));
6215 entries += sizeof (dir_entry);
6222 resource_tree_free (ResTreeNode * node)
6225 for (list = node->children; list; list = list->next)
6226 resource_tree_free ((ResTreeNode*)list->data);
6227 g_slist_free(node->children);
6232 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6237 MonoReflectionWin32Resource *win32_res;
6240 if (!assemblyb->win32_resources)
6244 * Resources are stored in a three level tree inside the PE file.
6245 * - level one contains a node for each type of resource
6246 * - level two contains a node for each resource
6247 * - level three contains a node for each instance of a resource for a
6248 * specific language.
6251 tree = resource_tree_create (assemblyb->win32_resources);
6253 /* Estimate the size of the encoded tree */
6255 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6256 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6257 size += mono_array_length (win32_res->res_data);
6259 /* Directory structure */
6260 size += mono_array_length (assemblyb->win32_resources) * 256;
6261 p = buf = (char *)g_malloc (size);
6263 resource_tree_encode (tree, p, p, &p);
6265 g_assert (p - buf <= size);
6267 assembly->win32_res = (char *)g_malloc (p - buf);
6268 assembly->win32_res_size = p - buf;
6269 memcpy (assembly->win32_res, buf, p - buf);
6272 resource_tree_free (tree);
6276 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6278 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6281 p += sizeof (MonoPEResourceDir);
6282 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6283 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6284 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6285 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6286 fixup_resource_directory (res_section, child, rva);
6288 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6289 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6292 p += sizeof (MonoPEResourceDirEntry);
6297 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6300 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6301 g_error ("WriteFile returned %d\n", GetLastError ());
6305 * mono_image_create_pefile:
6306 * @mb: a module builder object
6308 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6309 * assembly->pefile where it can be easily retrieved later in chunks.
6312 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6314 MonoMSDOSHeader *msdos;
6315 MonoDotNetHeader *header;
6316 MonoSectionTable *section;
6317 MonoCLIHeader *cli_header;
6318 guint32 size, image_size, virtual_base, text_offset;
6319 guint32 header_start, section_start, file_offset, virtual_offset;
6320 MonoDynamicImage *assembly;
6321 MonoReflectionAssemblyBuilder *assemblyb;
6322 MonoDynamicStream pefile_stream = {0};
6323 MonoDynamicStream *pefile = &pefile_stream;
6325 guint32 *rva, value;
6327 static const unsigned char msheader[] = {
6328 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6329 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6332 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6333 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6334 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6335 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6338 mono_error_init (error);
6340 assemblyb = mb->assemblyb;
6342 mono_image_basic_init (assemblyb);
6343 assembly = mb->dynamic_image;
6345 assembly->pe_kind = assemblyb->pe_kind;
6346 assembly->machine = assemblyb->machine;
6347 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6348 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6350 if (!mono_image_build_metadata (mb, error))
6354 if (mb->is_main && assemblyb->resources) {
6355 int len = mono_array_length (assemblyb->resources);
6356 for (i = 0; i < len; ++i)
6357 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6360 if (mb->resources) {
6361 int len = mono_array_length (mb->resources);
6362 for (i = 0; i < len; ++i)
6363 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6366 if (!build_compressed_metadata (assembly, error))
6370 assembly_add_win32_resources (assembly, assemblyb);
6372 nsections = calc_section_size (assembly);
6374 /* The DOS header and stub */
6375 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6376 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6378 /* the dotnet header */
6379 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6381 /* the section tables */
6382 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6384 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6385 virtual_offset = VIRT_ALIGN;
6388 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6389 if (!assembly->sections [i].size)
6392 file_offset += FILE_ALIGN - 1;
6393 file_offset &= ~(FILE_ALIGN - 1);
6394 virtual_offset += VIRT_ALIGN - 1;
6395 virtual_offset &= ~(VIRT_ALIGN - 1);
6397 assembly->sections [i].offset = file_offset;
6398 assembly->sections [i].rva = virtual_offset;
6400 file_offset += assembly->sections [i].size;
6401 virtual_offset += assembly->sections [i].size;
6402 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6405 file_offset += FILE_ALIGN - 1;
6406 file_offset &= ~(FILE_ALIGN - 1);
6408 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6410 /* back-patch info */
6411 msdos = (MonoMSDOSHeader*)pefile->data;
6412 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6414 header = (MonoDotNetHeader*)(pefile->data + header_start);
6415 header->pesig [0] = 'P';
6416 header->pesig [1] = 'E';
6418 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6419 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6420 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6421 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6422 if (assemblyb->pekind == 1) {
6424 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6427 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6430 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6432 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6433 header->pe.pe_major = 6;
6434 header->pe.pe_minor = 0;
6435 size = assembly->sections [MONO_SECTION_TEXT].size;
6436 size += FILE_ALIGN - 1;
6437 size &= ~(FILE_ALIGN - 1);
6438 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6439 size = assembly->sections [MONO_SECTION_RSRC].size;
6440 size += FILE_ALIGN - 1;
6441 size &= ~(FILE_ALIGN - 1);
6442 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6443 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6444 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6445 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6446 /* pe_rva_entry_point always at the beginning of the text section */
6447 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6449 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6450 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6451 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6452 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6453 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6454 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6455 size = section_start;
6456 size += FILE_ALIGN - 1;
6457 size &= ~(FILE_ALIGN - 1);
6458 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6460 size += VIRT_ALIGN - 1;
6461 size &= ~(VIRT_ALIGN - 1);
6462 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6465 // Translate the PEFileKind value to the value expected by the Windows loader
6471 // PEFileKinds.Dll == 1
6472 // PEFileKinds.ConsoleApplication == 2
6473 // PEFileKinds.WindowApplication == 3
6476 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6477 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6479 if (assemblyb->pekind == 3)
6484 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6486 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6487 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6488 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6489 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6490 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6491 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6493 /* fill data directory entries */
6495 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6496 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6498 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6499 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6501 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6502 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6503 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6504 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6505 /* patch entrypoint name */
6506 if (assemblyb->pekind == 1)
6507 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6509 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6510 /* patch imported function RVA name */
6511 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6512 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6514 /* the import table */
6515 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6516 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6517 /* patch imported dll RVA name and other entries in the dir */
6518 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6519 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6520 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6521 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6522 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6523 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6525 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6526 value = (assembly->text_rva + assembly->imp_names_offset);
6527 *p++ = (value) & 0xff;
6528 *p++ = (value >> 8) & (0xff);
6529 *p++ = (value >> 16) & (0xff);
6530 *p++ = (value >> 24) & (0xff);
6532 /* the CLI header info */
6533 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6534 cli_header->ch_size = GUINT32_FROM_LE (72);
6535 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6536 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6537 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6538 if (assemblyb->entry_point) {
6539 guint32 table_idx = 0;
6540 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6541 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6542 table_idx = methodb->table_idx;
6544 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6546 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6548 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6550 /* The embedded managed resources */
6551 text_offset = assembly->text_rva + assembly->code.index;
6552 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6553 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6554 text_offset += assembly->resources.index;
6555 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6556 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6557 text_offset += assembly->meta_size;
6558 if (assembly->strong_name_size) {
6559 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6560 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6561 text_offset += assembly->strong_name_size;
6564 /* write the section tables and section content */
6565 section = (MonoSectionTable*)(pefile->data + section_start);
6566 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6567 static const char section_names [][7] = {
6568 ".text", ".rsrc", ".reloc"
6570 if (!assembly->sections [i].size)
6572 strcpy (section->st_name, section_names [i]);
6573 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6574 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6575 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6576 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6577 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6578 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6579 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6583 checked_write_file (file, pefile->data, pefile->index);
6585 mono_dynamic_stream_reset (pefile);
6587 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6588 if (!assembly->sections [i].size)
6591 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6592 g_error ("SetFilePointer returned %d\n", GetLastError ());
6595 case MONO_SECTION_TEXT:
6596 /* patch entry point */
6597 p = (guchar*)(assembly->code.data + 2);
6598 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6599 *p++ = (value) & 0xff;
6600 *p++ = (value >> 8) & 0xff;
6601 *p++ = (value >> 16) & 0xff;
6602 *p++ = (value >> 24) & 0xff;
6604 checked_write_file (file, assembly->code.data, assembly->code.index);
6605 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6606 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6607 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6610 g_free (assembly->image.raw_metadata);
6612 case MONO_SECTION_RELOC: {
6616 guint16 type_and_offset;
6620 g_assert (sizeof (reloc) == 12);
6622 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6623 reloc.block_size = GUINT32_FROM_LE (12);
6626 * the entrypoint is always at the start of the text section
6627 * 3 is IMAGE_REL_BASED_HIGHLOW
6628 * 2 is patch_size_rva - text_rva
6630 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6633 checked_write_file (file, &reloc, sizeof (reloc));
6637 case MONO_SECTION_RSRC:
6638 if (assembly->win32_res) {
6640 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6641 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6642 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6646 g_assert_not_reached ();
6650 /* check that the file is properly padded */
6651 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6652 g_error ("SetFilePointer returned %d\n", GetLastError ());
6653 if (! SetEndOfFile (file))
6654 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6656 mono_dynamic_stream_reset (&assembly->code);
6657 mono_dynamic_stream_reset (&assembly->us);
6658 mono_dynamic_stream_reset (&assembly->blob);
6659 mono_dynamic_stream_reset (&assembly->guid);
6660 mono_dynamic_stream_reset (&assembly->sheap);
6662 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6663 g_hash_table_destroy (assembly->blob_cache);
6664 assembly->blob_cache = NULL;
6669 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6672 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6674 g_assert_not_reached ();
6677 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6679 #ifndef DISABLE_REFLECTION_EMIT
6681 MonoReflectionModule *
6682 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6686 MonoImageOpenStatus status;
6687 MonoDynamicAssembly *assembly;
6688 guint32 module_count;
6689 MonoImage **new_modules;
6690 gboolean *new_modules_loaded;
6692 mono_error_init (error);
6694 name = mono_string_to_utf8 (fileName);
6696 image = mono_image_open (name, &status);
6698 if (status == MONO_IMAGE_ERROR_ERRNO)
6699 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6701 mono_error_set_bad_image_name (error, name, NULL);
6708 assembly = ab->dynamic_assembly;
6709 image->assembly = (MonoAssembly*)assembly;
6711 module_count = image->assembly->image->module_count;
6712 new_modules = g_new0 (MonoImage *, module_count + 1);
6713 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6715 if (image->assembly->image->modules)
6716 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6717 if (image->assembly->image->modules_loaded)
6718 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6719 new_modules [module_count] = image;
6720 new_modules_loaded [module_count] = TRUE;
6721 mono_image_addref (image);
6723 g_free (image->assembly->image->modules);
6724 image->assembly->image->modules = new_modules;
6725 image->assembly->image->modules_loaded = new_modules_loaded;
6726 image->assembly->image->module_count ++;
6728 mono_assembly_load_references (image, &status);
6730 mono_image_close (image);
6731 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6735 return mono_module_get_object_checked (mono_domain_get (), image, error);
6738 #endif /* DISABLE_REFLECTION_EMIT */
6741 * We need to return always the same object for MethodInfo, FieldInfo etc..
6742 * but we need to consider the reflected type.
6743 * type uses a different hash, since it uses custom hash/equal functions.
6748 MonoClass *refclass;
6752 reflected_equal (gconstpointer a, gconstpointer b) {
6753 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6754 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6756 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6760 reflected_hash (gconstpointer a) {
6761 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6762 return mono_aligned_addr_hash (ea->item);
6765 #define CHECK_OBJECT(t,p,k) \
6771 mono_domain_lock (domain); \
6772 if (!domain->refobject_hash) \
6773 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"); \
6774 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6775 mono_domain_unlock (domain); \
6778 mono_domain_unlock (domain); \
6781 #ifdef HAVE_BOEHM_GC
6782 /* ReflectedEntry doesn't need to be GC tracked */
6783 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6784 #define FREE_REFENTRY(entry) g_free ((entry))
6785 #define REFENTRY_REQUIRES_CLEANUP
6787 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6789 #define FREE_REFENTRY(entry)
6792 #define CACHE_OBJECT(t,p,o,k) \
6795 ReflectedEntry pe; \
6797 pe.refclass = (k); \
6798 mono_domain_lock (domain); \
6799 if (!domain->refobject_hash) \
6800 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"); \
6801 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6803 ReflectedEntry *e = ALLOC_REFENTRY; \
6805 e->refclass = (k); \
6806 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6809 mono_domain_unlock (domain); \
6814 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6816 mono_domain_lock (domain);
6817 if (domain->refobject_hash) {
6819 gpointer orig_pe, orig_value;
6822 pe.refclass = klass;
6823 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6824 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6825 FREE_REFENTRY (orig_pe);
6828 mono_domain_unlock (domain);
6831 #ifdef REFENTRY_REQUIRES_CLEANUP
6833 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6835 FREE_REFENTRY (key);
6840 mono_reflection_cleanup_domain (MonoDomain *domain)
6842 if (domain->refobject_hash) {
6843 /*let's avoid scanning the whole hashtable if not needed*/
6844 #ifdef REFENTRY_REQUIRES_CLEANUP
6845 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6847 mono_g_hash_table_destroy (domain->refobject_hash);
6848 domain->refobject_hash = NULL;
6852 #ifndef DISABLE_REFLECTION_EMIT
6854 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6856 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6860 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6862 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6866 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6868 MonoDynamicImage *image = moduleb->dynamic_image;
6869 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6870 mono_error_init (error);
6873 MonoImage **new_modules;
6875 char *name, *fqname;
6877 * FIXME: we already created an image in mono_image_basic_init (), but
6878 * we don't know which module it belongs to, since that is only
6879 * determined at assembly save time.
6881 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6882 name = mono_string_to_utf8 (ab->name);
6883 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6884 if (!is_ok (error)) {
6888 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6890 moduleb->module.image = &image->image;
6891 moduleb->dynamic_image = image;
6892 register_module (mono_object_domain (moduleb), moduleb, image);
6894 /* register the module with the assembly */
6895 ass = ab->dynamic_assembly->assembly.image;
6896 module_count = ass->module_count;
6897 new_modules = g_new0 (MonoImage *, module_count + 1);
6900 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6901 new_modules [module_count] = &image->image;
6902 mono_image_addref (&image->image);
6904 g_free (ass->modules);
6905 ass->modules = new_modules;
6906 ass->module_count ++;
6912 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6915 (void) image_module_basic_init (moduleb, &error);
6916 mono_error_set_pending_exception (&error);
6920 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6922 MonoDynamicImage *image = moduleb->dynamic_image;
6924 g_assert (type->type);
6925 image->wrappers_type = mono_class_from_mono_type (type->type);
6931 * mono_assembly_get_object:
6932 * @domain: an app domain
6933 * @assembly: an assembly
6935 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6937 MonoReflectionAssembly*
6938 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6941 MonoReflectionAssembly *result;
6942 result = mono_assembly_get_object_checked (domain, assembly, &error);
6943 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6947 * mono_assembly_get_object_checked:
6948 * @domain: an app domain
6949 * @assembly: an assembly
6951 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6953 MonoReflectionAssembly*
6954 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6956 MonoReflectionAssembly *res;
6958 mono_error_init (error);
6960 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6961 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6964 res->assembly = assembly;
6966 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6971 MonoReflectionModule*
6972 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6975 MonoReflectionModule *result;
6976 result = mono_module_get_object_checked (domain, image, &error);
6977 mono_error_cleanup (&error);
6981 MonoReflectionModule*
6982 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6984 MonoReflectionModule *res;
6987 mono_error_init (error);
6988 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6989 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6994 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6997 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6999 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7000 basename = g_path_get_basename (image->name);
7001 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7002 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7006 if (image->assembly->image == image) {
7007 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7011 if (image->assembly->image->modules) {
7012 for (i = 0; i < image->assembly->image->module_count; i++) {
7013 if (image->assembly->image->modules [i] == image)
7014 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7016 g_assert (res->token);
7020 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7023 MonoReflectionModule*
7024 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7027 MonoReflectionModule *result;
7028 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7029 mono_error_cleanup (&error);
7033 MonoReflectionModule*
7034 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7036 MonoReflectionModule *res;
7037 MonoTableInfo *table;
7038 guint32 cols [MONO_FILE_SIZE];
7040 guint32 i, name_idx;
7043 mono_error_init (error);
7045 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7049 table = &image->tables [MONO_TABLE_FILE];
7050 g_assert (table_index < table->rows);
7051 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7054 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7057 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7058 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7060 /* Check whenever the row has a corresponding row in the moduleref table */
7061 table = &image->tables [MONO_TABLE_MODULEREF];
7062 for (i = 0; i < table->rows; ++i) {
7063 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7064 val = mono_metadata_string_heap (image, name_idx);
7065 if (strcmp (val, name) == 0)
7066 res->image = image->modules [i];
7069 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7070 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7071 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7072 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7073 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7079 verify_safe_for_managed_space (MonoType *type)
7081 switch (type->type) {
7083 case MONO_TYPE_ARRAY:
7084 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7086 return verify_safe_for_managed_space (type->data.type);
7087 case MONO_TYPE_SZARRAY:
7088 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7089 case MONO_TYPE_GENERICINST: {
7090 MonoGenericInst *inst = type->data.generic_class->inst;
7094 for (i = 0; i < inst->type_argc; ++i)
7095 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7101 case MONO_TYPE_MVAR:
7109 mono_type_normalize (MonoType *type)
7112 MonoGenericClass *gclass;
7113 MonoGenericInst *ginst;
7115 MonoGenericContainer *gcontainer;
7116 MonoType **argv = NULL;
7117 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7119 if (type->type != MONO_TYPE_GENERICINST)
7122 gclass = type->data.generic_class;
7123 ginst = gclass->context.class_inst;
7124 if (!ginst->is_open)
7127 gtd = gclass->container_class;
7128 gcontainer = gtd->generic_container;
7129 argv = g_newa (MonoType*, ginst->type_argc);
7131 for (i = 0; i < ginst->type_argc; ++i) {
7132 MonoType *t = ginst->type_argv [i], *norm;
7133 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7134 is_denorm_gtd = FALSE;
7135 norm = mono_type_normalize (t);
7138 requires_rebind = TRUE;
7142 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7144 if (requires_rebind) {
7145 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7146 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7152 * mono_type_get_object:
7153 * @domain: an app domain
7156 * Return an System.MonoType object representing the type @type.
7159 mono_type_get_object (MonoDomain *domain, MonoType *type)
7162 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7163 mono_error_cleanup (&error);
7169 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7171 MonoType *norm_type;
7172 MonoReflectionType *res;
7175 mono_error_init (error);
7177 klass = mono_class_from_mono_type (type);
7179 /*we must avoid using @type as it might have come
7180 * from a mono_metadata_type_dup and the caller
7181 * expects that is can be freed.
7182 * Using the right type from
7184 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7186 /* void is very common */
7187 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7188 return (MonoReflectionType*)domain->typeof_void;
7191 * If the vtable of the given class was already created, we can use
7192 * the MonoType from there and avoid all locking and hash table lookups.
7194 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7195 * that the resulting object is different.
7197 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7198 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7199 if (vtable && vtable->type)
7200 return (MonoReflectionType *)vtable->type;
7203 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7204 mono_domain_lock (domain);
7205 if (!domain->type_hash)
7206 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7207 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7208 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7209 mono_domain_unlock (domain);
7210 mono_loader_unlock ();
7214 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7215 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7216 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7217 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7218 * artifact of how generics are encoded and should be transparent to managed code so we
7219 * need to weed out this diference when retrieving managed System.Type objects.
7221 norm_type = mono_type_normalize (type);
7222 if (norm_type != type) {
7223 res = mono_type_get_object_checked (domain, norm_type, error);
7224 if (!mono_error_ok (error))
7226 mono_g_hash_table_insert (domain->type_hash, type, res);
7227 mono_domain_unlock (domain);
7228 mono_loader_unlock ();
7232 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7233 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7236 if (!verify_safe_for_managed_space (type)) {
7237 mono_domain_unlock (domain);
7238 mono_loader_unlock ();
7239 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7243 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7244 gboolean is_type_done = TRUE;
7245 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7246 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7247 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7249 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7250 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7252 if (gparam->owner && gparam->owner->is_method) {
7253 MonoMethod *method = gparam->owner->owner.method;
7254 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7255 is_type_done = FALSE;
7256 } else if (gparam->owner && !gparam->owner->is_method) {
7257 MonoClass *klass = gparam->owner->owner.klass;
7258 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7259 is_type_done = FALSE;
7263 /* g_assert_not_reached (); */
7264 /* should this be considered an error condition? */
7265 if (is_type_done && !type->byref) {
7266 mono_domain_unlock (domain);
7267 mono_loader_unlock ();
7268 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7271 /* This is stored in vtables/JITted code so it has to be pinned */
7272 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7273 if (!mono_error_ok (error))
7277 mono_g_hash_table_insert (domain->type_hash, type, res);
7279 if (type->type == MONO_TYPE_VOID)
7280 domain->typeof_void = (MonoObject*)res;
7282 mono_domain_unlock (domain);
7283 mono_loader_unlock ();
7288 * mono_method_get_object:
7289 * @domain: an app domain
7291 * @refclass: the reflected type (can be NULL)
7293 * Return an System.Reflection.MonoMethod object representing the method @method.
7295 MonoReflectionMethod*
7296 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7299 MonoReflectionMethod *ret = NULL;
7300 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7301 mono_error_cleanup (&error);
7306 * mono_method_get_object_checked:
7307 * @domain: an app domain
7309 * @refclass: the reflected type (can be NULL)
7310 * @error: set on error.
7312 * Return an System.Reflection.MonoMethod object representing the method @method.
7313 * Returns NULL and sets @error on error.
7315 MonoReflectionMethod*
7316 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7319 * We use the same C representation for methods and constructors, but the type
7320 * name in C# is different.
7322 MonoReflectionType *rt;
7324 MonoReflectionMethod *ret;
7326 mono_error_init (error);
7328 if (method->is_inflated) {
7329 MonoReflectionGenericMethod *gret;
7332 refclass = method->klass;
7333 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7334 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7335 klass = mono_class_get_mono_generic_cmethod_class ();
7337 klass = mono_class_get_mono_generic_method_class ();
7339 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7340 if (!mono_error_ok (error))
7342 gret->method.method = method;
7344 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7346 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7347 if (!mono_error_ok (error))
7350 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7352 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7356 refclass = method->klass;
7358 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7359 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7360 klass = mono_class_get_mono_cmethod_class ();
7363 klass = mono_class_get_mono_method_class ();
7365 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7366 if (!mono_error_ok (error))
7368 ret->method = method;
7370 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7371 if (!mono_error_ok (error))
7374 MONO_OBJECT_SETREF (ret, reftype, rt);
7376 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7379 g_assert (!mono_error_ok (error));
7384 * mono_method_clear_object:
7386 * Clear the cached reflection objects for the dynamic method METHOD.
7389 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7392 g_assert (method_is_dynamic (method));
7394 klass = method->klass;
7396 clear_cached_object (domain, method, klass);
7397 klass = klass->parent;
7399 /* Added by mono_param_get_objects () */
7400 clear_cached_object (domain, &(method->signature), NULL);
7401 klass = method->klass;
7403 clear_cached_object (domain, &(method->signature), klass);
7404 klass = klass->parent;
7409 * mono_field_get_object:
7410 * @domain: an app domain
7414 * Return an System.Reflection.MonoField object representing the field @field
7417 MonoReflectionField*
7418 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7421 MonoReflectionField *result;
7422 result = mono_field_get_object_checked (domain, klass, field, &error);
7423 mono_error_cleanup (&error);
7428 * mono_field_get_object_checked:
7429 * @domain: an app domain
7432 * @error: set on error
7434 * Return an System.Reflection.MonoField object representing the field @field
7435 * in class @klass. On error, returns NULL and sets @error.
7437 MonoReflectionField*
7438 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7440 MonoReflectionType *rt;
7441 MonoReflectionField *res;
7443 mono_error_init (error);
7445 CHECK_OBJECT (MonoReflectionField *, field, klass);
7446 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7451 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7453 if (is_field_on_inst (field)) {
7454 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7456 rt = mono_type_get_object_checked (domain, field->type, error);
7457 if (!mono_error_ok (error))
7460 MONO_OBJECT_SETREF (res, type, rt);
7463 rt = mono_type_get_object_checked (domain, field->type, error);
7464 if (!mono_error_ok (error))
7467 MONO_OBJECT_SETREF (res, type, rt);
7469 res->attrs = mono_field_get_flags (field);
7471 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7475 * mono_property_get_object:
7476 * @domain: an app domain
7478 * @property: a property
7480 * Return an System.Reflection.MonoProperty object representing the property @property
7483 MonoReflectionProperty*
7484 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7487 MonoReflectionProperty *result;
7488 result = mono_property_get_object_checked (domain, klass, property, &error);
7489 mono_error_cleanup (&error);
7494 * mono_property_get_object:
7495 * @domain: an app domain
7497 * @property: a property
7498 * @error: set on error
7500 * Return an System.Reflection.MonoProperty object representing the property @property
7501 * in class @klass. On error returns NULL and sets @error.
7503 MonoReflectionProperty*
7504 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7506 MonoReflectionProperty *res;
7508 mono_error_init (error);
7510 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7511 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7515 res->property = property;
7516 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7520 * mono_event_get_object:
7521 * @domain: an app domain
7525 * Return an System.Reflection.MonoEvent object representing the event @event
7528 MonoReflectionEvent*
7529 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7532 MonoReflectionEvent *result;
7533 result = mono_event_get_object_checked (domain, klass, event, &error);
7534 mono_error_cleanup (&error);
7539 * mono_event_get_object_checked:
7540 * @domain: an app domain
7543 * @error: set on error
7545 * Return an System.Reflection.MonoEvent object representing the event @event
7546 * in class @klass. On failure sets @error and returns NULL
7548 MonoReflectionEvent*
7549 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7551 MonoReflectionEvent *res;
7552 MonoReflectionMonoEvent *mono_event;
7554 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7555 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7558 mono_event->klass = klass;
7559 mono_event->event = event;
7560 res = (MonoReflectionEvent*)mono_event;
7561 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7565 * mono_get_reflection_missing_object:
7566 * @domain: Domain where the object lives
7568 * Returns the System.Reflection.Missing.Value singleton object
7569 * (of type System.Reflection.Missing).
7571 * Used as the value for ParameterInfo.DefaultValue when Optional
7575 mono_get_reflection_missing_object (MonoDomain *domain)
7579 static MonoClassField *missing_value_field = NULL;
7581 if (!missing_value_field) {
7582 MonoClass *missing_klass;
7583 missing_klass = mono_class_get_missing_class ();
7584 mono_class_init (missing_klass);
7585 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7586 g_assert (missing_value_field);
7588 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7589 mono_error_assert_ok (&error);
7594 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7597 *dbnull = mono_get_dbnull_object (domain);
7602 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7604 if (!*reflection_missing)
7605 *reflection_missing = mono_get_reflection_missing_object (domain);
7606 return *reflection_missing;
7610 * mono_param_get_objects:
7611 * @domain: an app domain
7614 * Return an System.Reflection.ParameterInfo array object representing the parameters
7615 * in the method @method.
7618 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7620 static MonoClass *System_Reflection_ParameterInfo;
7621 static MonoClass *System_Reflection_ParameterInfo_array;
7622 MonoArray *res = NULL;
7623 MonoReflectionMethod *member = NULL;
7624 MonoReflectionParameter *param = NULL;
7625 char **names = NULL, **blobs = NULL;
7626 guint32 *types = NULL;
7627 MonoType *type = NULL;
7628 MonoObject *dbnull = NULL;
7629 MonoObject *missing = NULL;
7630 MonoMarshalSpec **mspecs = NULL;
7631 MonoMethodSignature *sig = NULL;
7632 MonoVTable *pinfo_vtable;
7633 MonoReflectionType *rt;
7636 mono_error_init (error);
7638 if (!System_Reflection_ParameterInfo_array) {
7641 klass = mono_class_get_mono_parameter_info_class ();
7643 mono_memory_barrier ();
7644 System_Reflection_ParameterInfo = klass;
7647 klass = mono_array_class_get (klass, 1);
7648 mono_memory_barrier ();
7649 System_Reflection_ParameterInfo_array = klass;
7652 sig = mono_method_signature_checked (method, error);
7653 if (!mono_error_ok (error))
7656 if (!sig->param_count) {
7657 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7664 /* Note: the cache is based on the address of the signature into the method
7665 * since we already cache MethodInfos with the method as keys.
7667 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7669 member = mono_method_get_object_checked (domain, method, refclass, error);
7672 names = g_new (char *, sig->param_count);
7673 mono_method_get_param_names (method, (const char **) names);
7675 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7676 mono_method_get_marshal_info (method, mspecs);
7678 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7682 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7683 for (i = 0; i < sig->param_count; ++i) {
7684 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7688 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7692 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7694 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7696 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7698 param->PositionImpl = i;
7699 param->AttrsImpl = sig->params [i]->attrs;
7701 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7702 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7703 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7705 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7709 blobs = g_new0 (char *, sig->param_count);
7710 types = g_new0 (guint32, sig->param_count);
7711 get_default_param_value_blobs (method, blobs, types);
7714 /* Build MonoType for the type from the Constant Table */
7716 type = g_new0 (MonoType, 1);
7717 type->type = (MonoTypeEnum)types [i];
7718 type->data.klass = NULL;
7719 if (types [i] == MONO_TYPE_CLASS)
7720 type->data.klass = mono_defaults.object_class;
7721 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7722 /* For enums, types [i] contains the base type */
7724 type->type = MONO_TYPE_VALUETYPE;
7725 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7727 type->data.klass = mono_class_from_mono_type (type);
7729 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7732 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7734 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7735 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7736 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7737 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7739 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7744 if (mspecs [i + 1]) {
7745 MonoReflectionMarshalAsAttribute* mobj;
7746 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7749 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7752 mono_array_setref (res, i, param);
7762 for (i = sig->param_count; i >= 0; i--) {
7764 mono_metadata_free_marshal_spec (mspecs [i]);
7772 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7776 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7779 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7780 mono_error_assert_ok (&error);
7785 * mono_method_body_get_object:
7786 * @domain: an app domain
7789 * Return an System.Reflection.MethodBody object representing the method @method.
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7795 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7796 mono_error_cleanup (&error);
7801 * mono_method_body_get_object_checked:
7802 * @domain: an app domain
7804 * @error: set on error
7806 * Return an System.Reflection.MethodBody object representing the
7807 * method @method. On failure, returns NULL and sets @error.
7809 MonoReflectionMethodBody*
7810 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7812 MonoReflectionMethodBody *ret;
7813 MonoMethodHeader *header;
7815 MonoReflectionType *rt;
7816 guint32 method_rva, local_var_sig_token;
7818 unsigned char format, flags;
7821 mono_error_init (error);
7823 /* for compatibility with .net */
7824 if (method_is_dynamic (method)) {
7825 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7829 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7831 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7832 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7833 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7834 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7835 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7838 image = method->klass->image;
7839 header = mono_method_get_header_checked (method, error);
7840 return_val_if_nok (error, NULL);
7842 if (!image_is_dynamic (image)) {
7843 /* Obtain local vars signature token */
7844 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7845 ptr = mono_image_rva_map (image, method_rva);
7846 flags = *(const unsigned char *) ptr;
7847 format = flags & METHOD_HEADER_FORMAT_MASK;
7849 case METHOD_HEADER_TINY_FORMAT:
7850 local_var_sig_token = 0;
7852 case METHOD_HEADER_FAT_FORMAT:
7856 local_var_sig_token = read32 (ptr);
7859 g_assert_not_reached ();
7862 local_var_sig_token = 0; //FIXME
7864 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7868 ret->init_locals = header->init_locals;
7869 ret->max_stack = header->max_stack;
7870 ret->local_var_sig_token = local_var_sig_token;
7871 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7872 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7875 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7876 for (i = 0; i < header->num_locals; ++i) {
7877 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7881 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7885 MONO_OBJECT_SETREF (info, local_type, rt);
7887 info->is_pinned = header->locals [i]->pinned;
7888 info->local_index = i;
7889 mono_array_setref (ret->locals, i, info);
7893 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7894 for (i = 0; i < header->num_clauses; ++i) {
7895 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7898 MonoExceptionClause *clause = &header->clauses [i];
7900 info->flags = clause->flags;
7901 info->try_offset = clause->try_offset;
7902 info->try_length = clause->try_len;
7903 info->handler_offset = clause->handler_offset;
7904 info->handler_length = clause->handler_len;
7905 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7906 info->filter_offset = clause->data.filter_offset;
7907 else if (clause->data.catch_class) {
7908 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7912 MONO_OBJECT_SETREF (info, catch_type, rt);
7915 mono_array_setref (ret->clauses, i, info);
7918 mono_metadata_free_mh (header);
7919 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7923 mono_metadata_free_mh (header);
7928 * mono_get_dbnull_object:
7929 * @domain: Domain where the object lives
7931 * Returns the System.DBNull.Value singleton object
7933 * Used as the value for ParameterInfo.DefaultValue
7936 mono_get_dbnull_object (MonoDomain *domain)
7940 static MonoClassField *dbnull_value_field = NULL;
7942 if (!dbnull_value_field) {
7943 MonoClass *dbnull_klass;
7944 dbnull_klass = mono_class_get_dbnull_class ();
7945 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7946 g_assert (dbnull_value_field);
7948 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7949 mono_error_assert_ok (&error);
7954 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7956 guint32 param_index, i, lastp, crow = 0;
7957 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7960 MonoClass *klass = method->klass;
7961 MonoImage *image = klass->image;
7962 MonoMethodSignature *methodsig = mono_method_signature (method);
7964 MonoTableInfo *constt;
7965 MonoTableInfo *methodt;
7966 MonoTableInfo *paramt;
7968 if (!methodsig->param_count)
7971 mono_class_init (klass);
7973 if (image_is_dynamic (klass->image)) {
7974 MonoReflectionMethodAux *aux;
7975 if (method->is_inflated)
7976 method = ((MonoMethodInflated*)method)->declaring;
7977 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7978 if (aux && aux->param_defaults) {
7979 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7980 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7985 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7986 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7987 constt = &image->tables [MONO_TABLE_CONSTANT];
7989 idx = mono_method_get_index (method) - 1;
7990 g_assert (idx != -1);
7992 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7993 if (idx + 1 < methodt->rows)
7994 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7996 lastp = paramt->rows + 1;
7998 for (i = param_index; i < lastp; ++i) {
8001 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8002 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8004 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8007 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8012 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8013 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8014 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8021 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8026 MonoType *basetype = type;
8028 mono_error_init (error);
8033 klass = mono_class_from_mono_type (type);
8034 if (klass->valuetype) {
8035 object = mono_object_new_checked (domain, klass, error);
8036 return_val_if_nok (error, NULL);
8037 retval = ((gchar *) object + sizeof (MonoObject));
8038 if (klass->enumtype)
8039 basetype = mono_class_enum_basetype (klass);
8044 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
8051 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8054 gboolean quoted = FALSE;
8056 memset (assembly, 0, sizeof (MonoAssemblyName));
8057 assembly->culture = "";
8058 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8065 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8076 /* Remove trailing whitespace */
8078 while (*s && g_ascii_isspace (*s))
8081 while (g_ascii_isspace (*p))
8084 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8086 assembly->major = strtoul (p, &s, 10);
8087 if (s == p || *s != '.')
8090 assembly->minor = strtoul (p, &s, 10);
8091 if (s == p || *s != '.')
8094 assembly->build = strtoul (p, &s, 10);
8095 if (s == p || *s != '.')
8098 assembly->revision = strtoul (p, &s, 10);
8102 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8104 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8105 assembly->culture = "";
8108 assembly->culture = p;
8109 while (*p && *p != ',') {
8113 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8115 if (strncmp (p, "null", 4) == 0) {
8120 while (*p && *p != ',') {
8123 len = (p - start + 1);
8124 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8125 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8126 g_strlcpy ((char*)assembly->public_key_token, start, len);
8129 while (*p && *p != ',')
8133 while (g_ascii_isspace (*p) || *p == ',') {
8147 * mono_reflection_parse_type:
8150 * Parse a type name as accepted by the GetType () method and output the info
8151 * extracted in the info structure.
8152 * the name param will be mangled, so, make a copy before passing it to this function.
8153 * The fields in info will be valid until the memory pointed to by name is valid.
8155 * See also mono_type_get_name () below.
8157 * Returns: 0 on parse error.
8160 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8161 MonoTypeNameParse *info)
8163 char *start, *p, *w, *last_point, *startn;
8164 int in_modifiers = 0;
8165 int isbyref = 0, rank = 0, isptr = 0;
8167 start = p = w = name;
8169 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8170 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8171 info->name = info->name_space = NULL;
8172 info->nested = NULL;
8173 info->modifiers = NULL;
8174 info->type_arguments = NULL;
8176 /* last_point separates the namespace from the name */
8179 while (*p == ' ') p++, start++, w++, name++;
8184 *p = 0; /* NULL terminate the name */
8186 info->nested = g_list_append (info->nested, startn);
8187 /* we have parsed the nesting namespace + name */
8191 info->name_space = start;
8193 info->name = last_point + 1;
8195 info->name_space = (char *)"";
8223 info->name_space = start;
8225 info->name = last_point + 1;
8227 info->name_space = (char *)"";
8234 if (isbyref) /* only one level allowed by the spec */
8238 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8242 if (isbyref) /* pointer to ref not okay */
8244 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8249 if (isbyref) /* array of ref and generic ref are not okay */
8251 //Decide if it's an array of a generic argument list
8256 if (*p == ',' || *p == '*' || *p == ']') { //array
8264 else if (*p == '*') /* '*' means unknown lower bound */
8265 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8272 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8274 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8277 info->type_arguments = g_ptr_array_new ();
8279 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8280 gboolean fqname = FALSE;
8282 g_ptr_array_add (info->type_arguments, subinfo);
8284 while (*p == ' ') p++;
8290 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8293 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8294 if (fqname && (*p != ']')) {
8302 while (*p && (*p != ']'))
8310 if (g_ascii_isspace (*aname)) {
8317 !assembly_name_to_aname (&subinfo->assembly, aname))
8319 } else if (fqname && (*p == ']')) {
8341 if (g_ascii_isspace (*p)) {
8348 return 0; /* missing assembly name */
8349 if (!assembly_name_to_aname (&info->assembly, p))
8355 if (info->assembly.name)
8358 // *w = 0; /* terminate class name */
8360 if (!info->name || !*info->name)
8364 /* add other consistency checks */
8370 * mono_identifier_unescape_type_name_chars:
8371 * @identifier: the display name of a mono type
8374 * The name in internal form, that is without escaping backslashes.
8376 * The string is modified in place!
8379 mono_identifier_unescape_type_name_chars(char* identifier)
8384 for (w = r = identifier; *r != 0; r++)
8402 mono_identifier_unescape_info (MonoTypeNameParse* info);
8405 unescape_each_type_argument(void* data, void* user_data)
8407 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8408 mono_identifier_unescape_info (info);
8412 unescape_each_nested_name (void* data, void* user_data)
8414 char* nested_name = (char*) data;
8415 mono_identifier_unescape_type_name_chars(nested_name);
8419 * mono_identifier_unescape_info:
8421 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8425 * Destructively updates the info by unescaping the identifiers that
8426 * comprise the type namespace, name, nested types (if any) and
8427 * generic type arguments (if any).
8429 * The resulting info has the names in internal form.
8433 mono_identifier_unescape_info (MonoTypeNameParse *info)
8437 mono_identifier_unescape_type_name_chars(info->name_space);
8438 mono_identifier_unescape_type_name_chars(info->name);
8439 // but don't escape info->assembly
8440 if (info->type_arguments)
8441 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8443 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8447 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8449 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8451 mono_identifier_unescape_info (info);
8457 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8459 gboolean type_resolve = FALSE;
8461 MonoImage *rootimage = image;
8463 mono_error_init (error);
8465 if (info->assembly.name) {
8466 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8467 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8469 * This could happen in the AOT compiler case when the search hook is not
8472 assembly = image->assembly;
8474 /* then we must load the assembly ourselve - see #60439 */
8475 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8479 image = assembly->image;
8480 } else if (!image) {
8481 image = mono_defaults.corlib;
8484 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8485 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8486 mono_error_cleanup (error);
8487 image = mono_defaults.corlib;
8488 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8495 * mono_reflection_get_type_internal:
8497 * Returns: may return NULL on success, sets error on failure.
8500 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8505 gboolean bounded = FALSE;
8507 mono_error_init (error);
8509 image = mono_defaults.corlib;
8512 rootimage = mono_defaults.corlib;
8515 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8517 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8522 for (mod = info->nested; mod; mod = mod->next) {
8523 gpointer iter = NULL;
8527 mono_class_init (parent);
8529 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8531 char *nested_name, *nested_nspace;
8532 gboolean match = TRUE;
8534 lastp = strrchr ((const char *)mod->data, '.');
8536 /* Nested classes can have namespaces */
8539 nested_name = g_strdup (lastp + 1);
8540 nspace_len = lastp - (char*)mod->data;
8541 nested_nspace = (char *)g_malloc (nspace_len + 1);
8542 memcpy (nested_nspace, mod->data, nspace_len);
8543 nested_nspace [nspace_len] = '\0';
8546 nested_name = (char *)mod->data;
8547 nested_nspace = NULL;
8550 if (nested_nspace) {
8552 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8555 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8561 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8564 if (strcmp (klass->name, nested_name) != 0)
8569 g_free (nested_name);
8570 g_free (nested_nspace);
8582 if (info->type_arguments) {
8583 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8584 MonoReflectionType *the_type;
8588 for (i = 0; i < info->type_arguments->len; i++) {
8589 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8591 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8592 if (!type_args [i]) {
8598 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8602 instance = mono_reflection_bind_generic_parameters (
8603 the_type, info->type_arguments->len, type_args, error);
8609 klass = mono_class_from_mono_type (instance);
8612 for (mod = info->modifiers; mod; mod = mod->next) {
8613 modval = GPOINTER_TO_UINT (mod->data);
8614 if (!modval) { /* byref: must be last modifier */
8615 return &klass->this_arg;
8616 } else if (modval == -1) {
8617 klass = mono_ptr_class_get (&klass->byval_arg);
8618 } else if (modval == -2) {
8620 } else { /* array rank */
8621 klass = mono_bounded_array_class_get (klass, modval, bounded);
8625 return &klass->byval_arg;
8629 * mono_reflection_get_type:
8630 * @image: a metadata context
8631 * @info: type description structure
8632 * @ignorecase: flag for case-insensitive string compares
8633 * @type_resolve: whenever type resolve was already tried
8635 * Build a MonoType from the type description in @info.
8640 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8642 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8643 mono_error_cleanup (&error);
8648 * mono_reflection_get_type_checked:
8649 * @rootimage: the image of the currently active managed caller
8650 * @image: a metadata context
8651 * @info: type description structure
8652 * @ignorecase: flag for case-insensitive string compares
8653 * @type_resolve: whenever type resolve was already tried
8654 * @error: set on error.
8656 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8660 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8661 mono_error_init (error);
8662 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8667 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8669 MonoReflectionAssemblyBuilder *abuilder;
8673 mono_error_init (error);
8674 g_assert (assembly_is_dynamic (assembly));
8675 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8679 /* Enumerate all modules */
8682 if (abuilder->modules) {
8683 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8684 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8685 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8688 if (!mono_error_ok (error))
8693 if (!type && abuilder->loaded_modules) {
8694 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8695 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8696 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8699 if (!mono_error_ok (error))
8708 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8711 MonoReflectionAssembly *assembly;
8715 mono_error_init (error);
8717 if (image && image_is_dynamic (image))
8718 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8720 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8722 return_val_if_nok (error, NULL);
8726 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8733 *type_resolve = TRUE;
8736 /* Reconstruct the type name */
8737 fullName = g_string_new ("");
8738 if (info->name_space && (info->name_space [0] != '\0'))
8739 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8741 g_string_printf (fullName, "%s", info->name);
8742 for (mod = info->nested; mod; mod = mod->next)
8743 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8745 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8746 if (!is_ok (error)) {
8747 g_string_free (fullName, TRUE);
8752 if (assembly_is_dynamic (assembly->assembly))
8753 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8754 info, ignorecase, error);
8756 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8757 info, ignorecase, error);
8759 g_string_free (fullName, TRUE);
8760 return_val_if_nok (error, NULL);
8765 mono_reflection_free_type_info (MonoTypeNameParse *info)
8767 g_list_free (info->modifiers);
8768 g_list_free (info->nested);
8770 if (info->type_arguments) {
8773 for (i = 0; i < info->type_arguments->len; i++) {
8774 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8776 mono_reflection_free_type_info (subinfo);
8777 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8781 g_ptr_array_free (info->type_arguments, TRUE);
8786 * mono_reflection_type_from_name:
8788 * @image: a metadata context (can be NULL).
8790 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8791 * it defaults to get the type from @image or, if @image is NULL or loading
8792 * from it fails, uses corlib.
8796 mono_reflection_type_from_name (char *name, MonoImage *image)
8799 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8800 mono_error_cleanup (&error);
8805 * mono_reflection_type_from_name_checked:
8807 * @image: a metadata context (can be NULL).
8808 * @error: set on errror.
8810 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8811 * it defaults to get the type from @image or, if @image is NULL or loading
8812 * from it fails, uses corlib. On failure returns NULL and sets @error.
8816 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8818 MonoType *type = NULL;
8819 MonoTypeNameParse info;
8822 mono_error_init (error);
8823 /* Make a copy since parse_type modifies its argument */
8824 tmp = g_strdup (name);
8826 /*g_print ("requested type %s\n", str);*/
8827 if (mono_reflection_parse_type (tmp, &info)) {
8828 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8829 if (!is_ok (error)) {
8831 mono_reflection_free_type_info (&info);
8837 mono_reflection_free_type_info (&info);
8842 * mono_reflection_get_token:
8844 * Return the metadata token of OBJ which should be an object
8845 * representing a metadata element.
8848 mono_reflection_get_token (MonoObject *obj)
8851 guint32 result = mono_reflection_get_token_checked (obj, &error);
8852 mono_error_assert_ok (&error);
8857 * mono_reflection_get_token_checked:
8859 * @error: set on error
8861 * Return the metadata token of @obj which should be an object
8862 * representing a metadata element. On failure sets @error.
8865 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8870 mono_error_init (error);
8872 klass = obj->vtable->klass;
8874 if (strcmp (klass->name, "MethodBuilder") == 0) {
8875 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8877 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8878 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8879 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8881 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8882 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8883 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8885 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8886 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8887 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8888 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8889 } else if (strcmp (klass->name, "MonoType") == 0) {
8890 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8891 return_val_if_nok (error, 0);
8892 MonoClass *mc = mono_class_from_mono_type (type);
8893 if (!mono_class_init (mc)) {
8894 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8898 token = mc->type_token;
8899 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8900 strcmp (klass->name, "MonoMethod") == 0 ||
8901 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8902 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8903 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8904 if (m->method->is_inflated) {
8905 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8906 return inflated->declaring->token;
8908 token = m->method->token;
8910 } else if (strcmp (klass->name, "MonoField") == 0) {
8911 MonoReflectionField *f = (MonoReflectionField*)obj;
8913 if (is_field_on_inst (f->field)) {
8914 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8916 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8917 int field_index = f->field - dgclass->fields;
8920 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8921 obj = dgclass->field_objects [field_index];
8922 return mono_reflection_get_token_checked (obj, error);
8925 token = mono_class_get_field_token (f->field);
8926 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8927 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8929 token = mono_class_get_property_token (p->property);
8930 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8931 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8933 token = mono_class_get_event_token (p->event);
8934 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8935 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8936 MonoClass *member_class = mono_object_class (p->MemberImpl);
8937 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8939 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8940 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8941 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8944 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8945 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8947 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8948 klass->name_space, klass->name);
8956 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8960 int slen = mono_metadata_decode_value (p, &p);
8962 mono_error_init (error);
8964 n = (char *)g_memdup (p, slen + 1);
8966 t = mono_reflection_type_from_name_checked (n, image, error);
8968 char *msg = g_strdup (mono_error_get_message (error));
8969 mono_error_cleanup (error);
8970 /* We don't free n, it's consumed by mono_error */
8971 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8978 return mono_class_from_mono_type (t);
8982 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8984 int slen, type = t->type;
8985 MonoClass *tklass = t->data.klass;
8987 mono_error_init (error);
8993 case MONO_TYPE_BOOLEAN: {
8994 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8999 case MONO_TYPE_CHAR:
9001 case MONO_TYPE_I2: {
9002 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9007 #if SIZEOF_VOID_P == 4
9013 case MONO_TYPE_I4: {
9014 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9019 #if SIZEOF_VOID_P == 8
9020 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9024 case MONO_TYPE_I8: {
9025 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9030 case MONO_TYPE_R8: {
9031 double *val = (double *)g_malloc (sizeof (double));
9036 case MONO_TYPE_VALUETYPE:
9037 if (t->data.klass->enumtype) {
9038 type = mono_class_enum_basetype (t->data.klass)->type;
9041 MonoClass *k = t->data.klass;
9043 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9044 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9050 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9053 case MONO_TYPE_STRING:
9054 if (*p == (char)0xFF) {
9058 slen = mono_metadata_decode_value (p, &p);
9060 return mono_string_new_len (mono_domain_get (), p, slen);
9061 case MONO_TYPE_CLASS: {
9062 MonoReflectionType *rt;
9065 if (*p == (char)0xFF) {
9070 slen = mono_metadata_decode_value (p, &p);
9071 n = (char *)g_memdup (p, slen + 1);
9073 t = mono_reflection_type_from_name_checked (n, image, error);
9075 char *msg = g_strdup (mono_error_get_message (error));
9076 mono_error_cleanup (error);
9077 /* We don't free n, it's consumed by mono_error */
9078 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9085 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9086 if (!mono_error_ok (error))
9091 case MONO_TYPE_OBJECT: {
9094 MonoClass *subc = NULL;
9099 } else if (subt == 0x0E) {
9100 type = MONO_TYPE_STRING;
9102 } else if (subt == 0x1D) {
9103 MonoType simple_type = {{0}};
9107 type = MONO_TYPE_SZARRAY;
9108 if (etype == 0x50) {
9109 tklass = mono_defaults.systemtype_class;
9110 } else if (etype == 0x55) {
9111 tklass = load_cattr_enum_type (image, p, &p, error);
9112 if (!mono_error_ok (error))
9116 /* See Partition II, Appendix B3 */
9117 etype = MONO_TYPE_OBJECT;
9118 simple_type.type = (MonoTypeEnum)etype;
9119 tklass = mono_class_from_mono_type (&simple_type);
9122 } else if (subt == 0x55) {
9125 slen = mono_metadata_decode_value (p, &p);
9126 n = (char *)g_memdup (p, slen + 1);
9128 t = mono_reflection_type_from_name_checked (n, image, error);
9130 char *msg = g_strdup (mono_error_get_message (error));
9131 mono_error_cleanup (error);
9132 /* We don't free n, it's consumed by mono_error */
9133 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9139 subc = mono_class_from_mono_type (t);
9140 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9141 MonoType simple_type = {{0}};
9142 simple_type.type = (MonoTypeEnum)subt;
9143 subc = mono_class_from_mono_type (&simple_type);
9145 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9147 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9149 if (mono_error_ok (error)) {
9150 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9151 g_assert (!subc->has_references);
9152 if (mono_error_ok (error))
9153 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9159 case MONO_TYPE_SZARRAY: {
9161 guint32 i, alen, basetype;
9164 if (alen == 0xffffffff) {
9168 arr = mono_array_new (mono_domain_get(), tklass, alen);
9169 basetype = tklass->byval_arg.type;
9170 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9171 basetype = mono_class_enum_basetype (tklass)->type;
9176 case MONO_TYPE_BOOLEAN:
9177 for (i = 0; i < alen; i++) {
9178 MonoBoolean val = *p++;
9179 mono_array_set (arr, MonoBoolean, i, val);
9182 case MONO_TYPE_CHAR:
9185 for (i = 0; i < alen; i++) {
9186 guint16 val = read16 (p);
9187 mono_array_set (arr, guint16, i, val);
9194 for (i = 0; i < alen; i++) {
9195 guint32 val = read32 (p);
9196 mono_array_set (arr, guint32, i, val);
9201 for (i = 0; i < alen; i++) {
9204 mono_array_set (arr, double, i, val);
9210 for (i = 0; i < alen; i++) {
9211 guint64 val = read64 (p);
9212 mono_array_set (arr, guint64, i, val);
9216 case MONO_TYPE_CLASS:
9217 case MONO_TYPE_OBJECT:
9218 case MONO_TYPE_STRING:
9219 case MONO_TYPE_SZARRAY:
9220 for (i = 0; i < alen; i++) {
9221 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9222 if (!mono_error_ok (error))
9224 mono_array_setref (arr, i, item);
9228 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9234 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9240 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9242 mono_error_init (error);
9244 gboolean is_ref = type_is_reference (t);
9246 void *val = load_cattr_value (image, t, p, end, error);
9247 if (!is_ok (error)) {
9254 return (MonoObject*)val;
9256 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9262 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9264 static MonoMethod *ctor;
9266 void *params [2], *unboxed;
9268 mono_error_init (error);
9271 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9273 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9274 return_val_if_nok (error, NULL);
9277 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9278 return_val_if_nok (error, NULL);
9279 unboxed = mono_object_unbox (retval);
9281 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9282 return_val_if_nok (error, NULL);
9288 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9290 static MonoMethod *ctor;
9292 void *unboxed, *params [2];
9294 mono_error_init (error);
9297 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9300 params [1] = typedarg;
9301 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9302 return_val_if_nok (error, NULL);
9304 unboxed = mono_object_unbox (retval);
9306 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9307 return_val_if_nok (error, NULL);
9313 type_is_reference (MonoType *type)
9315 switch (type->type) {
9316 case MONO_TYPE_BOOLEAN:
9317 case MONO_TYPE_CHAR:
9330 case MONO_TYPE_VALUETYPE:
9338 free_param_data (MonoMethodSignature *sig, void **params) {
9340 for (i = 0; i < sig->param_count; ++i) {
9341 if (!type_is_reference (sig->params [i]))
9342 g_free (params [i]);
9347 * Find the field index in the metadata FieldDef table.
9350 find_field_index (MonoClass *klass, MonoClassField *field) {
9353 for (i = 0; i < klass->field.count; ++i) {
9354 if (field == &klass->fields [i])
9355 return klass->field.first + 1 + i;
9361 * Find the property index in the metadata Property table.
9364 find_property_index (MonoClass *klass, MonoProperty *property) {
9367 for (i = 0; i < klass->ext->property.count; ++i) {
9368 if (property == &klass->ext->properties [i])
9369 return klass->ext->property.first + 1 + i;
9375 * Find the event index in the metadata Event table.
9378 find_event_index (MonoClass *klass, MonoEvent *event) {
9381 for (i = 0; i < klass->ext->event.count; ++i) {
9382 if (event == &klass->ext->events [i])
9383 return klass->ext->event.first + 1 + i;
9389 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9391 const char *p = (const char*)data;
9393 guint32 i, j, num_named;
9395 void *params_buf [32];
9396 void **params = NULL;
9397 MonoMethodSignature *sig;
9399 mono_error_init (error);
9401 mono_class_init (method->klass);
9403 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9404 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9409 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9410 if (!mono_error_ok (error)) return NULL;
9412 mono_runtime_invoke_checked (method, attr, NULL, error);
9413 if (!mono_error_ok (error))
9419 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9422 /*g_print ("got attr %s\n", method->klass->name);*/
9424 sig = mono_method_signature (method);
9425 if (sig->param_count < 32) {
9426 params = params_buf;
9427 memset (params, 0, sizeof (void*) * sig->param_count);
9429 /* Allocate using GC so it gets GC tracking */
9430 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9435 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9436 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9437 if (!mono_error_ok (error))
9442 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9443 if (!mono_error_ok (error)) goto fail;
9445 MonoObject *exc = NULL;
9446 mono_runtime_try_invoke (method, attr, params, &exc, error);
9447 if (!mono_error_ok (error))
9450 mono_error_set_exception_instance (error, (MonoException*)exc);
9454 num_named = read16 (named);
9456 for (j = 0; j < num_named; j++) {
9458 char *name, named_type, data_type;
9459 named_type = *named++;
9460 data_type = *named++; /* type of data */
9461 if (data_type == MONO_TYPE_SZARRAY)
9462 data_type = *named++;
9463 if (data_type == MONO_TYPE_ENUM) {
9466 type_len = mono_metadata_decode_blob_size (named, &named);
9467 type_name = (char *)g_malloc (type_len + 1);
9468 memcpy (type_name, named, type_len);
9469 type_name [type_len] = 0;
9471 /* FIXME: lookup the type and check type consistency */
9474 name_len = mono_metadata_decode_blob_size (named, &named);
9475 name = (char *)g_malloc (name_len + 1);
9476 memcpy (name, named, name_len);
9477 name [name_len] = 0;
9479 if (named_type == 0x53) {
9480 MonoClassField *field;
9483 /* how this fail is a blackbox */
9484 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9486 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9491 val = load_cattr_value (image, field->type, named, &named, error);
9492 if (!mono_error_ok (error)) {
9494 if (!type_is_reference (field->type))
9499 mono_field_set_value (attr, field, val);
9500 if (!type_is_reference (field->type))
9502 } else if (named_type == 0x54) {
9505 MonoType *prop_type;
9507 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9510 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9516 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9521 /* can we have more that 1 arg in a custom attr named property? */
9522 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9523 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9525 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9526 if (!mono_error_ok (error)) {
9528 if (!type_is_reference (prop_type))
9529 g_free (pparams [0]);
9534 mono_property_set_value (prop, attr, pparams, NULL);
9535 if (!type_is_reference (prop_type))
9536 g_free (pparams [0]);
9541 free_param_data (method->signature, params);
9542 if (params != params_buf)
9543 mono_gc_free_fixed (params);
9548 free_param_data (method->signature, params);
9549 if (params != params_buf)
9550 mono_gc_free_fixed (params);
9555 * mono_reflection_create_custom_attr_data_args:
9557 * Create an array of typed and named arguments from the cattr blob given by DATA.
9558 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9559 * NAMED_ARG_INFO will contain information about the named arguments.
9562 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)
9564 MonoArray *typedargs, *namedargs;
9565 MonoClass *attrklass;
9567 const char *p = (const char*)data;
9569 guint32 i, j, num_named;
9570 CattrNamedArg *arginfo = NULL;
9574 *named_arg_info = NULL;
9576 mono_error_init (error);
9578 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9579 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9583 mono_class_init (method->klass);
9585 domain = mono_domain_get ();
9587 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9590 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9594 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9597 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9598 return_if_nok (error);
9599 mono_array_setref (typedargs, i, obj);
9603 num_named = read16 (named);
9604 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9606 attrklass = method->klass;
9608 arginfo = g_new0 (CattrNamedArg, num_named);
9609 *named_arg_info = arginfo;
9611 for (j = 0; j < num_named; j++) {
9613 char *name, named_type, data_type;
9614 named_type = *named++;
9615 data_type = *named++; /* type of data */
9616 if (data_type == MONO_TYPE_SZARRAY)
9617 data_type = *named++;
9618 if (data_type == MONO_TYPE_ENUM) {
9621 type_len = mono_metadata_decode_blob_size (named, &named);
9622 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9625 type_name = (char *)g_malloc (type_len + 1);
9626 memcpy (type_name, named, type_len);
9627 type_name [type_len] = 0;
9629 /* FIXME: lookup the type and check type consistency */
9632 name_len = mono_metadata_decode_blob_size (named, &named);
9633 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9635 name = (char *)g_malloc (name_len + 1);
9636 memcpy (name, named, name_len);
9637 name [name_len] = 0;
9639 if (named_type == 0x53) {
9641 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9648 arginfo [j].type = field->type;
9649 arginfo [j].field = field;
9651 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9652 if (!is_ok (error)) {
9656 mono_array_setref (namedargs, j, obj);
9658 } else if (named_type == 0x54) {
9660 MonoType *prop_type;
9661 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9663 if (!prop || !prop->set) {
9668 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9669 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9671 arginfo [j].type = prop_type;
9672 arginfo [j].prop = prop;
9674 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9675 if (!is_ok (error)) {
9679 mono_array_setref (namedargs, j, obj);
9684 *typed_args = typedargs;
9685 *named_args = namedargs;
9688 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9690 *named_arg_info = NULL;
9694 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9697 MonoArray *typedargs, *namedargs;
9700 CattrNamedArg *arginfo = NULL;
9703 mono_error_init (error);
9711 image = assembly->assembly->image;
9712 method = ref_method->method;
9713 domain = mono_object_domain (ref_method);
9715 if (!mono_class_init (method->klass)) {
9716 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->klass));
9720 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9724 if (!typedargs || !namedargs)
9727 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9728 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9729 MonoObject *typedarg;
9731 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9734 mono_array_setref (typedargs, i, typedarg);
9737 for (i = 0; i < mono_array_length (namedargs); ++i) {
9738 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9739 MonoObject *typedarg, *namedarg, *minfo;
9741 if (arginfo [i].prop) {
9742 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9746 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9751 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9754 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9758 mono_array_setref (namedargs, i, namedarg);
9761 *ctor_args = typedargs;
9762 *named_args = namedargs;
9766 return mono_error_ok (error);
9770 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9773 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9774 mono_error_set_pending_exception (&error);
9778 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9780 static MonoMethod *ctor;
9786 mono_error_init (error);
9788 g_assert (image->assembly);
9791 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9793 domain = mono_domain_get ();
9794 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9795 return_val_if_nok (error, NULL);
9796 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9797 return_val_if_nok (error, NULL);
9798 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9799 return_val_if_nok (error, NULL);
9800 params [2] = (gpointer)&cattr->data;
9801 params [3] = &cattr->data_size;
9803 mono_runtime_invoke_checked (ctor, attr, params, error);
9804 return_val_if_nok (error, NULL);
9809 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9815 mono_error_init (error);
9818 for (i = 0; i < cinfo->num_attrs; ++i) {
9819 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9823 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9825 for (i = 0; i < cinfo->num_attrs; ++i) {
9826 if (!cinfo->attrs [i].ctor) {
9827 /* The cattr type is not finished yet */
9828 /* We should include the type name but cinfo doesn't contain it */
9829 mono_error_set_type_load_name (error, NULL, NULL, "");
9832 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9833 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9834 if (!mono_error_ok (error))
9836 mono_array_setref (result, n, attr);
9844 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9847 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9848 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9854 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9860 mono_error_init (error);
9861 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9862 for (i = 0; i < cinfo->num_attrs; ++i) {
9863 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9864 return_val_if_nok (error, NULL);
9865 mono_array_setref (result, i, attr);
9871 * mono_custom_attrs_from_index:
9873 * Returns: NULL if no attributes are found or if a loading error occurs.
9876 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9879 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9880 mono_error_cleanup (&error);
9884 * mono_custom_attrs_from_index_checked:
9886 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9889 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9891 guint32 mtoken, i, len;
9892 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9894 MonoCustomAttrInfo *ainfo;
9895 GList *tmp, *list = NULL;
9897 MonoCustomAttrEntry* attr;
9899 mono_error_init (error);
9901 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9903 i = mono_metadata_custom_attrs_from_index (image, idx);
9907 while (i < ca->rows) {
9908 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9910 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9913 len = g_list_length (list);
9916 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9917 ainfo->num_attrs = len;
9918 ainfo->image = image;
9919 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9920 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9921 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9922 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9923 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9924 mtoken |= MONO_TOKEN_METHOD_DEF;
9926 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9927 mtoken |= MONO_TOKEN_MEMBER_REF;
9930 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9933 attr = &ainfo->attrs [i - 1];
9934 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9936 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9942 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9943 /*FIXME raising an exception here doesn't make any sense*/
9944 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9949 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9950 attr->data_size = mono_metadata_decode_value (data, &data);
9951 attr->data = (guchar*)data;
9959 mono_custom_attrs_from_method (MonoMethod *method)
9962 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9963 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9968 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9972 mono_error_init (error);
9975 * An instantiated method has the same cattrs as the generic method definition.
9977 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9978 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9980 if (method->is_inflated)
9981 method = ((MonoMethodInflated *) method)->declaring;
9983 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9984 return lookup_custom_attr (method->klass->image, method);
9987 /* Synthetic methods */
9990 idx = mono_method_get_index (method);
9991 idx <<= MONO_CUSTOM_ATTR_BITS;
9992 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9993 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9997 mono_custom_attrs_from_class (MonoClass *klass)
10000 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10001 mono_error_cleanup (&error);
10005 MonoCustomAttrInfo*
10006 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10010 mono_error_init (error);
10012 if (klass->generic_class)
10013 klass = klass->generic_class->container_class;
10015 if (image_is_dynamic (klass->image))
10016 return lookup_custom_attr (klass->image, klass);
10018 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10019 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10020 idx <<= MONO_CUSTOM_ATTR_BITS;
10021 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10023 idx = mono_metadata_token_index (klass->type_token);
10024 idx <<= MONO_CUSTOM_ATTR_BITS;
10025 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10027 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10030 MonoCustomAttrInfo*
10031 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10034 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10035 mono_error_cleanup (&error);
10039 MonoCustomAttrInfo*
10040 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10044 mono_error_init (error);
10046 if (image_is_dynamic (assembly->image))
10047 return lookup_custom_attr (assembly->image, assembly);
10048 idx = 1; /* there is only one assembly */
10049 idx <<= MONO_CUSTOM_ATTR_BITS;
10050 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10051 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10054 static MonoCustomAttrInfo*
10055 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10059 if (image_is_dynamic (image))
10060 return lookup_custom_attr (image, image);
10061 idx = 1; /* there is only one module */
10062 idx <<= MONO_CUSTOM_ATTR_BITS;
10063 idx |= MONO_CUSTOM_ATTR_MODULE;
10064 return mono_custom_attrs_from_index_checked (image, idx, error);
10067 MonoCustomAttrInfo*
10068 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10071 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10072 mono_error_cleanup (&error);
10076 MonoCustomAttrInfo*
10077 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10081 if (image_is_dynamic (klass->image)) {
10082 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10083 return lookup_custom_attr (klass->image, property);
10085 idx = find_property_index (klass, property);
10086 idx <<= MONO_CUSTOM_ATTR_BITS;
10087 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10088 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10091 MonoCustomAttrInfo*
10092 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10095 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10096 mono_error_cleanup (&error);
10100 MonoCustomAttrInfo*
10101 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10105 if (image_is_dynamic (klass->image)) {
10106 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10107 return lookup_custom_attr (klass->image, event);
10109 idx = find_event_index (klass, event);
10110 idx <<= MONO_CUSTOM_ATTR_BITS;
10111 idx |= MONO_CUSTOM_ATTR_EVENT;
10112 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10115 MonoCustomAttrInfo*
10116 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10119 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10120 mono_error_cleanup (&error);
10124 MonoCustomAttrInfo*
10125 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10128 mono_error_init (error);
10130 if (image_is_dynamic (klass->image)) {
10131 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10132 return lookup_custom_attr (klass->image, field);
10134 idx = find_field_index (klass, field);
10135 idx <<= MONO_CUSTOM_ATTR_BITS;
10136 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10137 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10141 * mono_custom_attrs_from_param:
10142 * @method: handle to the method that we want to retrieve custom parameter information from
10143 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10145 * The result must be released with mono_custom_attrs_free().
10147 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10149 MonoCustomAttrInfo*
10150 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10153 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10154 mono_error_cleanup (&error);
10159 * mono_custom_attrs_from_param_checked:
10160 * @method: handle to the method that we want to retrieve custom parameter information from
10161 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10162 * @error: set on error
10164 * The result must be released with mono_custom_attrs_free().
10166 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10168 MonoCustomAttrInfo*
10169 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10172 guint32 i, idx, method_index;
10173 guint32 param_list, param_last, param_pos, found;
10175 MonoReflectionMethodAux *aux;
10177 mono_error_init (error);
10180 * An instantiated method has the same cattrs as the generic method definition.
10182 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10183 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10185 if (method->is_inflated)
10186 method = ((MonoMethodInflated *) method)->declaring;
10188 if (image_is_dynamic (method->klass->image)) {
10189 MonoCustomAttrInfo *res, *ainfo;
10192 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10193 if (!aux || !aux->param_cattr)
10196 /* Need to copy since it will be freed later */
10197 ainfo = aux->param_cattr [param];
10200 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10201 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10202 memcpy (res, ainfo, size);
10206 image = method->klass->image;
10207 method_index = mono_method_get_index (method);
10210 ca = &image->tables [MONO_TABLE_METHOD];
10212 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10213 if (method_index == ca->rows) {
10214 ca = &image->tables [MONO_TABLE_PARAM];
10215 param_last = ca->rows + 1;
10217 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10218 ca = &image->tables [MONO_TABLE_PARAM];
10221 for (i = param_list; i < param_last; ++i) {
10222 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10223 if (param_pos == param) {
10231 idx <<= MONO_CUSTOM_ATTR_BITS;
10232 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10233 return mono_custom_attrs_from_index_checked (image, idx, error);
10237 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10241 for (i = 0; i < ainfo->num_attrs; ++i) {
10242 klass = ainfo->attrs [i].ctor->klass;
10243 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10250 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10253 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10254 mono_error_assert_ok (&error); /*FIXME proper error handling*/
10259 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10265 mono_error_init (error);
10268 for (i = 0; i < ainfo->num_attrs; ++i) {
10269 klass = ainfo->attrs [i].ctor->klass;
10270 if (mono_class_has_parent (klass, attr_klass)) {
10275 if (attr_index == -1)
10278 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10279 if (!mono_error_ok (error))
10281 return mono_array_get (attrs, MonoObject*, attr_index);
10285 * mono_reflection_get_custom_attrs_info:
10286 * @obj: a reflection object handle
10288 * Return the custom attribute info for attributes defined for the
10289 * reflection handle @obj. The objects.
10291 * FIXME this function leaks like a sieve for SRE objects.
10293 MonoCustomAttrInfo*
10294 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10297 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10298 mono_error_assert_ok (&error);
10303 * mono_reflection_get_custom_attrs_info_checked:
10304 * @obj: a reflection object handle
10305 * @error: set on error
10307 * Return the custom attribute info for attributes defined for the
10308 * reflection handle @obj. The objects.
10310 * On failure returns NULL and sets @error.
10312 * FIXME this function leaks like a sieve for SRE objects.
10314 MonoCustomAttrInfo*
10315 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10318 MonoCustomAttrInfo *cinfo = NULL;
10320 mono_error_init (error);
10322 klass = obj->vtable->klass;
10323 if (klass == mono_defaults.monotype_class) {
10324 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10325 return_val_if_nok (error, NULL);
10326 klass = mono_class_from_mono_type (type);
10327 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10328 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10329 return_val_if_nok (error, NULL);
10330 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10331 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10332 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10333 return_val_if_nok (error, NULL);
10334 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10335 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10336 cinfo = mono_custom_attrs_from_module (module->image, error);
10337 return_val_if_nok (error, NULL);
10338 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10339 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10340 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10341 return_val_if_nok (error, NULL);
10342 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10343 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10344 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10345 return_val_if_nok (error, NULL);
10346 } else if (strcmp ("MonoField", klass->name) == 0) {
10347 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10348 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10349 return_val_if_nok (error, NULL);
10350 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10351 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10352 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10353 return_val_if_nok (error, NULL);
10354 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10355 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10356 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10357 return_val_if_nok (error, NULL);
10358 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10359 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10360 MonoClass *member_class = mono_object_class (param->MemberImpl);
10361 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10362 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10363 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10364 return_val_if_nok (error, NULL);
10365 } else if (is_sr_mono_property (member_class)) {
10366 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10367 MonoMethod *method;
10368 if (!(method = prop->property->get))
10369 method = prop->property->set;
10372 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10373 return_val_if_nok (error, NULL);
10375 #ifndef DISABLE_REFLECTION_EMIT
10376 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10377 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10378 return_val_if_nok (error, NULL);
10379 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10380 return_val_if_nok (error, NULL);
10381 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10382 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10383 MonoMethod *method = NULL;
10384 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10385 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10386 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10387 method = ((MonoReflectionMethod *)c->cb)->method;
10389 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));
10391 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10392 return_val_if_nok (error, NULL);
10396 char *type_name = mono_type_get_full_name (member_class);
10397 mono_error_set_not_supported (error,
10398 "Custom attributes on a ParamInfo with member %s are not supported",
10400 g_free (type_name);
10403 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10404 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10405 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10406 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10407 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10408 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10409 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10410 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10411 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10412 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10413 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10414 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10415 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10416 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10417 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10418 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10419 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10420 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10421 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10422 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10423 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10424 return_val_if_nok (error, NULL);
10425 } else { /* handle other types here... */
10426 g_error ("get custom attrs not yet supported for %s", klass->name);
10433 * mono_reflection_get_custom_attrs_by_type:
10434 * @obj: a reflection object handle
10436 * Return an array with all the custom attributes defined of the
10437 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10438 * of that type are returned. The objects are fully build. Return NULL if a loading error
10442 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10445 MonoCustomAttrInfo *cinfo;
10447 mono_error_init (error);
10449 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10450 return_val_if_nok (error, NULL);
10452 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10453 if (!cinfo->cached)
10454 mono_custom_attrs_free (cinfo);
10458 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10465 * mono_reflection_get_custom_attrs:
10466 * @obj: a reflection object handle
10468 * Return an array with all the custom attributes defined of the
10469 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10473 mono_reflection_get_custom_attrs (MonoObject *obj)
10477 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10481 * mono_reflection_get_custom_attrs_data:
10482 * @obj: a reflection obj handle
10484 * Returns an array of System.Reflection.CustomAttributeData,
10485 * which include information about attributes reflected on
10486 * types loaded using the Reflection Only methods
10489 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10493 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10494 mono_error_cleanup (&error);
10499 * mono_reflection_get_custom_attrs_data_checked:
10500 * @obj: a reflection obj handle
10501 * @error: set on error
10503 * Returns an array of System.Reflection.CustomAttributeData,
10504 * which include information about attributes reflected on
10505 * types loaded using the Reflection Only methods
10508 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10511 MonoCustomAttrInfo *cinfo;
10513 mono_error_init (error);
10515 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10516 return_val_if_nok (error, NULL);
10518 result = mono_custom_attrs_data_construct (cinfo, error);
10519 if (!cinfo->cached)
10520 mono_custom_attrs_free (cinfo);
10521 return_val_if_nok (error, NULL);
10523 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10528 static MonoReflectionType*
10529 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10531 static MonoMethod *method_get_underlying_system_type = NULL;
10532 MonoReflectionType *rt;
10533 MonoMethod *usertype_method;
10535 mono_error_init (error);
10537 if (!method_get_underlying_system_type)
10538 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10540 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10542 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10549 is_corlib_type (MonoClass *klass)
10551 return klass->image == mono_defaults.corlib;
10554 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10555 static MonoClass *cached_class; \
10556 if (cached_class) \
10557 return cached_class == _class; \
10558 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10559 cached_class = _class; \
10566 #ifndef DISABLE_REFLECTION_EMIT
10568 is_sre_array (MonoClass *klass)
10570 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10574 is_sre_byref (MonoClass *klass)
10576 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10580 is_sre_pointer (MonoClass *klass)
10582 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10586 is_sre_generic_instance (MonoClass *klass)
10588 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10592 is_sre_type_builder (MonoClass *klass)
10594 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10598 is_sre_method_builder (MonoClass *klass)
10600 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10604 is_sre_ctor_builder (MonoClass *klass)
10606 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10610 is_sre_field_builder (MonoClass *klass)
10612 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10616 is_sre_method_on_tb_inst (MonoClass *klass)
10618 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10622 is_sre_ctor_on_tb_inst (MonoClass *klass)
10624 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10628 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10631 mono_error_init (error);
10638 if (is_usertype (ref)) {
10639 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10640 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10646 klass = mono_object_class (ref);
10648 if (is_sre_array (klass)) {
10650 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10651 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10652 return_val_if_nok (error, NULL);
10654 if (sre_array->rank == 0) //single dimentional array
10655 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10657 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10658 sre_array->type.type = res;
10660 } else if (is_sre_byref (klass)) {
10662 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10663 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10664 return_val_if_nok (error, NULL);
10666 res = &mono_class_from_mono_type (base)->this_arg;
10667 sre_byref->type.type = res;
10669 } else if (is_sre_pointer (klass)) {
10671 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10672 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10673 return_val_if_nok (error, NULL);
10675 res = &mono_ptr_class_get (base)->byval_arg;
10676 sre_pointer->type.type = res;
10678 } else if (is_sre_generic_instance (klass)) {
10679 MonoType *res, **types;
10680 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10683 count = mono_array_length (gclass->type_arguments);
10684 types = g_new0 (MonoType*, count);
10685 for (i = 0; i < count; ++i) {
10686 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10687 types [i] = mono_reflection_type_get_handle (t, error);
10688 if (!types[i] || !is_ok (error)) {
10694 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10697 gclass->type.type = res;
10701 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10706 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10709 mono_reflection_type_get_handle (type, &error);
10710 mono_error_set_pending_exception (&error);
10714 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10716 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10719 mono_error_init (error);
10721 MonoType *res = mono_reflection_type_get_handle (type, error);
10723 if (!res && is_ok (error)) {
10724 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10726 return_val_if_nok (error, FALSE);
10728 klass = mono_class_from_mono_type (res);
10730 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10731 mono_domain_lock (domain);
10733 if (!image_is_dynamic (klass->image)) {
10734 mono_class_setup_supertypes (klass);
10736 if (!domain->type_hash)
10737 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10738 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10739 mono_g_hash_table_insert (domain->type_hash, res, type);
10741 mono_domain_unlock (domain);
10742 mono_loader_unlock ();
10748 mono_reflection_register_with_runtime (MonoReflectionType *type)
10751 (void) reflection_register_with_runtime (type, &error);
10752 mono_error_set_pending_exception (&error);
10756 * LOCKING: Assumes the loader lock is held.
10758 static MonoMethodSignature*
10759 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10760 MonoMethodSignature *sig;
10763 mono_error_init (error);
10765 count = parameters? mono_array_length (parameters): 0;
10767 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10768 sig->param_count = count;
10769 sig->sentinelpos = -1; /* FIXME */
10770 for (i = 0; i < count; ++i) {
10771 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10772 if (!is_ok (error)) {
10773 image_g_free (image, sig);
10781 * LOCKING: Assumes the loader lock is held.
10783 static MonoMethodSignature*
10784 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10785 MonoMethodSignature *sig;
10787 mono_error_init (error);
10789 sig = parameters_to_signature (image, ctor->parameters, error);
10790 return_val_if_nok (error, NULL);
10791 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10792 sig->ret = &mono_defaults.void_class->byval_arg;
10797 * LOCKING: Assumes the loader lock is held.
10799 static MonoMethodSignature*
10800 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10801 MonoMethodSignature *sig;
10803 mono_error_init (error);
10805 sig = parameters_to_signature (image, method->parameters, error);
10806 return_val_if_nok (error, NULL);
10807 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10808 if (method->rtype) {
10809 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10810 if (!is_ok (error)) {
10811 image_g_free (image, sig);
10815 sig->ret = &mono_defaults.void_class->byval_arg;
10817 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10821 static MonoMethodSignature*
10822 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10823 MonoMethodSignature *sig;
10825 mono_error_init (error);
10827 sig = parameters_to_signature (NULL, method->parameters, error);
10828 return_val_if_nok (error, NULL);
10829 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10830 if (method->rtype) {
10831 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10832 if (!is_ok (error)) {
10837 sig->ret = &mono_defaults.void_class->byval_arg;
10839 sig->generic_param_count = 0;
10844 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10846 mono_error_init (error);
10847 MonoClass *klass = mono_object_class (prop);
10848 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10849 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10850 *name = mono_string_to_utf8 (pb->name);
10851 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10853 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10854 *name = g_strdup (p->property->name);
10855 if (p->property->get)
10856 *type = mono_method_signature (p->property->get)->ret;
10858 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10863 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10865 mono_error_init (error);
10866 MonoClass *klass = mono_object_class (field);
10867 if (strcmp (klass->name, "FieldBuilder") == 0) {
10868 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10869 *name = mono_string_to_utf8 (fb->name);
10870 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10872 MonoReflectionField *f = (MonoReflectionField *)field;
10873 *name = g_strdup (mono_field_get_name (f->field));
10874 *type = f->field->type;
10878 #else /* DISABLE_REFLECTION_EMIT */
10881 mono_reflection_register_with_runtime (MonoReflectionType *type)
10883 /* This is empty */
10887 is_sre_type_builder (MonoClass *klass)
10893 is_sre_generic_instance (MonoClass *klass)
10899 init_type_builder_generics (MonoObject *type, MonoError *error)
10901 mono_error_init (error);
10904 #endif /* !DISABLE_REFLECTION_EMIT */
10908 is_sr_mono_field (MonoClass *klass)
10910 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10914 is_sr_mono_property (MonoClass *klass)
10916 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10920 is_sr_mono_method (MonoClass *klass)
10922 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10926 is_sr_mono_cmethod (MonoClass *klass)
10928 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10932 is_sr_mono_generic_method (MonoClass *klass)
10934 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10938 is_sr_mono_generic_cmethod (MonoClass *klass)
10940 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10944 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10946 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10950 is_usertype (MonoReflectionType *ref)
10952 MonoClass *klass = mono_object_class (ref);
10953 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10956 static MonoReflectionType*
10957 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10959 mono_error_init (error);
10960 if (!type || type->type)
10963 if (is_usertype (type)) {
10964 type = mono_reflection_type_get_underlying_system_type (type, error);
10965 return_val_if_nok (error, NULL);
10966 if (is_usertype (type)) {
10967 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10975 * encode_cattr_value:
10976 * Encode a value in a custom attribute stream of bytes.
10977 * The value to encode is either supplied as an object in argument val
10978 * (valuetypes are boxed), or as a pointer to the data in the
10980 * @type represents the type of the value
10981 * @buffer is the start of the buffer
10982 * @p the current position in the buffer
10983 * @buflen contains the size of the buffer and is used to return the new buffer size
10984 * if this needs to be realloced.
10985 * @retbuffer and @retp return the start and the position of the buffer
10986 * @error set on error.
10989 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10991 MonoTypeEnum simple_type;
10993 mono_error_init (error);
10994 if ((p-buffer) + 10 >= *buflen) {
10997 newbuf = (char *)g_realloc (buffer, *buflen);
10998 p = newbuf + (p-buffer);
11002 argval = ((char*)arg + sizeof (MonoObject));
11003 simple_type = type->type;
11005 switch (simple_type) {
11006 case MONO_TYPE_BOOLEAN:
11011 case MONO_TYPE_CHAR:
11014 swap_with_size (p, argval, 2, 1);
11020 swap_with_size (p, argval, 4, 1);
11024 swap_with_size (p, argval, 8, 1);
11029 swap_with_size (p, argval, 8, 1);
11032 case MONO_TYPE_VALUETYPE:
11033 if (type->data.klass->enumtype) {
11034 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11037 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11040 case MONO_TYPE_STRING: {
11047 str = mono_string_to_utf8 ((MonoString*)arg);
11048 slen = strlen (str);
11049 if ((p-buffer) + 10 + slen >= *buflen) {
11053 newbuf = (char *)g_realloc (buffer, *buflen);
11054 p = newbuf + (p-buffer);
11057 mono_metadata_encode_value (slen, p, &p);
11058 memcpy (p, str, slen);
11063 case MONO_TYPE_CLASS: {
11066 MonoType *arg_type;
11072 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11073 return_if_nok (error);
11075 str = type_get_qualified_name (arg_type, NULL);
11076 slen = strlen (str);
11077 if ((p-buffer) + 10 + slen >= *buflen) {
11081 newbuf = (char *)g_realloc (buffer, *buflen);
11082 p = newbuf + (p-buffer);
11085 mono_metadata_encode_value (slen, p, &p);
11086 memcpy (p, str, slen);
11091 case MONO_TYPE_SZARRAY: {
11093 MonoClass *eclass, *arg_eclass;
11096 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11099 len = mono_array_length ((MonoArray*)arg);
11101 *p++ = (len >> 8) & 0xff;
11102 *p++ = (len >> 16) & 0xff;
11103 *p++ = (len >> 24) & 0xff;
11105 *retbuffer = buffer;
11106 eclass = type->data.klass;
11107 arg_eclass = mono_object_class (arg)->element_class;
11110 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11111 eclass = mono_defaults.object_class;
11113 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11114 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11115 int elsize = mono_class_array_element_size (arg_eclass);
11116 for (i = 0; i < len; ++i) {
11117 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11118 return_if_nok (error);
11121 } else if (eclass->valuetype && arg_eclass->valuetype) {
11122 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11123 int elsize = mono_class_array_element_size (eclass);
11124 for (i = 0; i < len; ++i) {
11125 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11126 return_if_nok (error);
11130 for (i = 0; i < len; ++i) {
11131 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11132 return_if_nok (error);
11137 case MONO_TYPE_OBJECT: {
11143 * The parameter type is 'object' but the type of the actual
11144 * argument is not. So we have to add type information to the blob
11145 * too. This is completely undocumented in the spec.
11149 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11154 klass = mono_object_class (arg);
11156 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11160 return_if_nok (error);
11163 if (klass->enumtype) {
11165 } else if (klass == mono_defaults.string_class) {
11166 simple_type = MONO_TYPE_STRING;
11169 } else if (klass->rank == 1) {
11171 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11172 /* See Partition II, Appendix B3 */
11175 *p++ = klass->element_class->byval_arg.type;
11176 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11177 return_if_nok (error);
11179 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11180 *p++ = simple_type = klass->byval_arg.type;
11183 g_error ("unhandled type in custom attr");
11185 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11186 slen = strlen (str);
11187 if ((p-buffer) + 10 + slen >= *buflen) {
11191 newbuf = (char *)g_realloc (buffer, *buflen);
11192 p = newbuf + (p-buffer);
11195 mono_metadata_encode_value (slen, p, &p);
11196 memcpy (p, str, slen);
11199 simple_type = mono_class_enum_basetype (klass)->type;
11203 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11206 *retbuffer = buffer;
11210 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11212 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11213 char *str = type_get_qualified_name (type, NULL);
11214 int slen = strlen (str);
11218 * This seems to be optional...
11221 mono_metadata_encode_value (slen, p, &p);
11222 memcpy (p, str, slen);
11225 } else if (type->type == MONO_TYPE_OBJECT) {
11227 } else if (type->type == MONO_TYPE_CLASS) {
11228 /* it should be a type: encode_cattr_value () has the check */
11231 mono_metadata_encode_value (type->type, p, &p);
11232 if (type->type == MONO_TYPE_SZARRAY)
11233 /* See the examples in Partition VI, Annex B */
11234 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11240 #ifndef DISABLE_REFLECTION_EMIT
11242 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11246 mono_error_init (error);
11248 /* Preallocate a large enough buffer */
11249 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11250 char *str = type_get_qualified_name (type, NULL);
11251 len = strlen (str);
11253 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11254 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11255 len = strlen (str);
11260 len += strlen (name);
11262 if ((p-buffer) + 20 + len >= *buflen) {
11266 newbuf = (char *)g_realloc (buffer, *buflen);
11267 p = newbuf + (p-buffer);
11271 encode_field_or_prop_type (type, p, &p);
11273 len = strlen (name);
11274 mono_metadata_encode_value (len, p, &p);
11275 memcpy (p, name, len);
11277 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11278 return_if_nok (error);
11280 *retbuffer = buffer;
11284 * mono_reflection_get_custom_attrs_blob:
11285 * @ctor: custom attribute constructor
11286 * @ctorArgs: arguments o the constructor
11292 * Creates the blob of data that needs to be saved in the metadata and that represents
11293 * the custom attributed described by @ctor, @ctorArgs etc.
11294 * Returns: a Byte array representing the blob of data.
11297 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11300 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11301 mono_error_cleanup (&error);
11306 * mono_reflection_get_custom_attrs_blob_checked:
11307 * @ctor: custom attribute constructor
11308 * @ctorArgs: arguments o the constructor
11313 * @error: set on error
11315 * Creates the blob of data that needs to be saved in the metadata and that represents
11316 * the custom attributed described by @ctor, @ctorArgs etc.
11317 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11320 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11322 MonoArray *result = NULL;
11323 MonoMethodSignature *sig;
11328 mono_error_init (error);
11330 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11331 /* sig is freed later so allocate it in the heap */
11332 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11333 if (!is_ok (error)) {
11338 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11341 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11343 p = buffer = (char *)g_malloc (buflen);
11344 /* write the prolog */
11347 for (i = 0; i < sig->param_count; ++i) {
11348 arg = mono_array_get (ctorArgs, MonoObject*, i);
11349 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11350 if (!is_ok (error)) goto leave;
11354 i += mono_array_length (properties);
11356 i += mono_array_length (fields);
11358 *p++ = (i >> 8) & 0xff;
11361 for (i = 0; i < mono_array_length (properties); ++i) {
11365 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11366 get_prop_name_and_type (prop, &pname, &ptype, error);
11367 if (!is_ok (error)) goto leave;
11368 *p++ = 0x54; /* PROPERTY signature */
11369 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11371 if (!is_ok (error)) goto leave;
11377 for (i = 0; i < mono_array_length (fields); ++i) {
11381 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11382 get_field_name_and_type (field, &fname, &ftype, error);
11383 if (!is_ok (error)) goto leave;
11384 *p++ = 0x53; /* FIELD signature */
11385 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11387 if (!is_ok (error)) goto leave;
11391 g_assert (p - buffer <= buflen);
11392 buflen = p - buffer;
11393 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11394 p = mono_array_addr (result, char, 0);
11395 memcpy (p, buffer, buflen);
11398 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11404 * reflection_setup_internal_class:
11405 * @tb: a TypeBuilder object
11406 * @error: set on error
11408 * Creates a MonoClass that represents the TypeBuilder.
11409 * This is a trick that lets us simplify a lot of reflection code
11410 * (and will allow us to support Build and Run assemblies easier).
11412 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11415 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11417 MonoClass *klass, *parent;
11419 mono_error_init (error);
11420 RESOLVE_TYPE (tb->parent, error);
11421 return_val_if_nok (error, FALSE);
11423 mono_loader_lock ();
11426 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11427 if (!is_ok (error)) {
11428 mono_loader_unlock ();
11431 /* check so we can compile corlib correctly */
11432 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11433 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11434 parent = parent_type->data.klass;
11436 parent = mono_class_from_mono_type (parent_type);
11442 /* the type has already being created: it means we just have to change the parent */
11443 if (tb->type.type) {
11444 klass = mono_class_from_mono_type (tb->type.type);
11445 klass->parent = NULL;
11446 /* fool mono_class_setup_parent */
11447 klass->supertypes = NULL;
11448 mono_class_setup_parent (klass, parent);
11449 mono_class_setup_mono_type (klass);
11450 mono_loader_unlock ();
11454 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11456 klass->image = &tb->module->dynamic_image->image;
11458 klass->inited = 1; /* we lie to the runtime */
11459 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11460 if (!is_ok (error))
11462 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11463 if (!is_ok (error))
11465 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11466 klass->flags = tb->attrs;
11468 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11470 klass->element_class = klass;
11472 if (mono_class_get_ref_info (klass) == NULL) {
11474 mono_class_set_ref_info (klass, tb);
11476 /* Put into cache so mono_class_get_checked () will find it.
11477 Skip nested types as those should not be available on the global scope. */
11478 if (!tb->nesting_type)
11479 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11482 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11483 by performing a mono_class_get which does the full resolution.
11485 Working around this semantics would require us to write a lot of code for no clear advantage.
11487 mono_image_append_class_to_reflection_info_set (klass);
11489 g_assert (mono_class_get_ref_info (klass) == tb);
11492 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11494 if (parent != NULL) {
11495 mono_class_setup_parent (klass, parent);
11496 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11497 const char *old_n = klass->name;
11498 /* trick to get relative numbering right when compiling corlib */
11499 klass->name = "BuildingObject";
11500 mono_class_setup_parent (klass, mono_defaults.object_class);
11501 klass->name = old_n;
11504 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11505 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11506 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11507 klass->instance_size = sizeof (MonoObject);
11508 klass->size_inited = 1;
11509 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11512 mono_class_setup_mono_type (klass);
11514 mono_class_setup_supertypes (klass);
11517 * FIXME: handle interfaces.
11520 tb->type.type = &klass->byval_arg;
11522 if (tb->nesting_type) {
11523 g_assert (tb->nesting_type->type);
11524 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11525 if (!is_ok (error)) goto failure;
11526 klass->nested_in = mono_class_from_mono_type (nesting_type);
11529 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11531 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11533 mono_loader_unlock ();
11537 mono_loader_unlock ();
11542 * mono_reflection_setup_internal_class:
11543 * @tb: a TypeBuilder object
11546 * Creates a MonoClass that represents the TypeBuilder.
11547 * This is a trick that lets us simplify a lot of reflection code
11548 * (and will allow us to support Build and Run assemblies easier).
11552 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11555 (void) reflection_setup_internal_class (tb, &error);
11556 mono_error_set_pending_exception (&error);
11560 * mono_reflection_setup_generic_class:
11561 * @tb: a TypeBuilder object
11563 * Setup the generic class before adding the first generic parameter.
11566 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11571 * mono_reflection_create_generic_class:
11572 * @tb: a TypeBuilder object
11573 * @error: set on error
11575 * Creates the generic class after all generic parameters have been added.
11576 * On success returns TRUE, on failure returns FALSE and sets @error.
11580 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11586 mono_error_init (error);
11588 klass = mono_class_from_mono_type (tb->type.type);
11590 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11592 if (klass->generic_container || (count == 0))
11595 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11597 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11599 klass->generic_container->owner.klass = klass;
11600 klass->generic_container->type_argc = count;
11601 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11603 klass->is_generic = 1;
11605 for (i = 0; i < count; i++) {
11606 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11607 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11608 return_val_if_nok (error, FALSE);
11609 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11610 klass->generic_container->type_params [i] = *param;
11611 /*Make sure we are a diferent type instance */
11612 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11613 klass->generic_container->type_params [i].info.pklass = NULL;
11614 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11616 g_assert (klass->generic_container->type_params [i].param.owner);
11619 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11624 * reflection_create_internal_class:
11625 * @tb: a TypeBuilder object
11626 * @error: set on error
11628 * Actually create the MonoClass that is associated with the TypeBuilder.
11629 * On success returns TRUE, on failure returns FALSE and sets @error.
11633 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11638 mono_error_init (error);
11639 klass = mono_class_from_mono_type (tb->type.type);
11641 mono_loader_lock ();
11642 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11643 MonoReflectionFieldBuilder *fb;
11645 MonoType *enum_basetype;
11647 g_assert (tb->fields != NULL);
11648 g_assert (mono_array_length (tb->fields) >= 1);
11650 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11652 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11653 if (!is_ok (error)) {
11654 mono_loader_unlock ();
11657 if (!mono_type_is_valid_enum_basetype (field_type)) {
11658 mono_loader_unlock ();
11662 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11663 if (!is_ok (error)) {
11664 mono_loader_unlock ();
11667 klass->element_class = mono_class_from_mono_type (enum_basetype);
11668 if (!klass->element_class)
11669 klass->element_class = mono_class_from_mono_type (enum_basetype);
11672 * get the element_class from the current corlib.
11674 ec = default_class_from_mono_type (enum_basetype);
11675 klass->instance_size = ec->instance_size;
11676 klass->size_inited = 1;
11678 * this is almost safe to do with enums and it's needed to be able
11679 * to create objects of the enum type (for use in SetConstant).
11681 /* FIXME: Does this mean enums can't have method overrides ? */
11682 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11684 mono_loader_unlock ();
11689 * mono_reflection_create_internal_class:
11690 * @tb: a TypeBuilder object
11693 * Actually create the MonoClass that is associated with the TypeBuilder.
11696 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11699 (void) reflection_create_internal_class (tb, &error);
11700 mono_error_set_pending_exception (&error);
11703 static MonoMarshalSpec*
11704 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11705 MonoReflectionMarshal *minfo, MonoError *error)
11707 MonoMarshalSpec *res;
11709 mono_error_init (error);
11711 res = image_g_new0 (image, MonoMarshalSpec, 1);
11712 res->native = (MonoMarshalNative)minfo->type;
11714 switch (minfo->type) {
11715 case MONO_NATIVE_LPARRAY:
11716 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11717 if (minfo->has_size) {
11718 res->data.array_data.param_num = minfo->param_num;
11719 res->data.array_data.num_elem = minfo->count;
11720 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11723 res->data.array_data.param_num = -1;
11724 res->data.array_data.num_elem = -1;
11725 res->data.array_data.elem_mult = -1;
11729 case MONO_NATIVE_BYVALTSTR:
11730 case MONO_NATIVE_BYVALARRAY:
11731 res->data.array_data.num_elem = minfo->count;
11734 case MONO_NATIVE_CUSTOM:
11735 if (minfo->marshaltyperef) {
11736 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11737 if (!is_ok (error)) {
11738 image_g_free (image, res);
11741 res->data.custom_data.custom_name =
11742 type_get_fully_qualified_name (marshaltyperef);
11744 if (minfo->mcookie)
11745 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11754 #endif /* !DISABLE_REFLECTION_EMIT */
11756 MonoReflectionMarshalAsAttribute*
11757 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11758 MonoMarshalSpec *spec, MonoError *error)
11760 MonoReflectionType *rt;
11761 MonoReflectionMarshalAsAttribute *minfo;
11764 mono_error_init (error);
11766 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11769 minfo->utype = spec->native;
11771 switch (minfo->utype) {
11772 case MONO_NATIVE_LPARRAY:
11773 minfo->array_subtype = spec->data.array_data.elem_type;
11774 minfo->size_const = spec->data.array_data.num_elem;
11775 if (spec->data.array_data.param_num != -1)
11776 minfo->size_param_index = spec->data.array_data.param_num;
11779 case MONO_NATIVE_BYVALTSTR:
11780 case MONO_NATIVE_BYVALARRAY:
11781 minfo->size_const = spec->data.array_data.num_elem;
11784 case MONO_NATIVE_CUSTOM:
11785 if (spec->data.custom_data.custom_name) {
11786 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11787 return_val_if_nok (error, NULL);
11790 rt = mono_type_get_object_checked (domain, mtype, error);
11794 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11797 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11799 if (spec->data.custom_data.cookie)
11800 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11810 #ifndef DISABLE_REFLECTION_EMIT
11812 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11813 ReflectionMethodBuilder *rmb,
11814 MonoMethodSignature *sig,
11818 MonoMethodWrapper *wrapperm;
11819 MonoMarshalSpec **specs;
11820 MonoReflectionMethodAux *method_aux;
11825 mono_error_init (error);
11827 * Methods created using a MethodBuilder should have their memory allocated
11828 * inside the image mempool, while dynamic methods should have their memory
11831 dynamic = rmb->refs != NULL;
11832 image = dynamic ? NULL : klass->image;
11835 g_assert (!klass->generic_class);
11837 mono_loader_lock ();
11839 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11840 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11841 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11843 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11845 wrapperm = (MonoMethodWrapper*)m;
11847 m->dynamic = dynamic;
11849 m->flags = rmb->attrs;
11850 m->iflags = rmb->iattrs;
11851 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11853 m->signature = sig;
11854 m->sre_method = TRUE;
11855 m->skip_visibility = rmb->skip_visibility;
11856 if (rmb->table_idx)
11857 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11859 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11860 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11861 m->string_ctor = 1;
11863 m->signature->pinvoke = 1;
11864 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11865 m->signature->pinvoke = 1;
11867 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11869 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11870 mono_error_assert_ok (error);
11871 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11872 mono_error_assert_ok (error);
11874 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11876 if (image_is_dynamic (klass->image))
11877 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11879 mono_loader_unlock ();
11882 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11883 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11884 MonoMethodHeader *header;
11886 gint32 max_stack, i;
11887 gint32 num_locals = 0;
11888 gint32 num_clauses = 0;
11892 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11893 code_size = rmb->ilgen->code_len;
11894 max_stack = rmb->ilgen->max_stack;
11895 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11896 if (rmb->ilgen->ex_handlers)
11897 num_clauses = method_count_clauses (rmb->ilgen);
11900 code = mono_array_addr (rmb->code, guint8, 0);
11901 code_size = mono_array_length (rmb->code);
11902 /* we probably need to run a verifier on the code... */
11912 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11913 header->code_size = code_size;
11914 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11915 memcpy ((char*)header->code, code, code_size);
11916 header->max_stack = max_stack;
11917 header->init_locals = rmb->init_locals;
11918 header->num_locals = num_locals;
11920 for (i = 0; i < num_locals; ++i) {
11921 MonoReflectionLocalBuilder *lb =
11922 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11924 header->locals [i] = image_g_new0 (image, MonoType, 1);
11925 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
11926 mono_error_assert_ok (error);
11927 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11930 header->num_clauses = num_clauses;
11932 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11933 rmb->ilgen, num_clauses, error);
11934 mono_error_assert_ok (error);
11937 wrapperm->header = header;
11940 if (rmb->generic_params) {
11941 int count = mono_array_length (rmb->generic_params);
11942 MonoGenericContainer *container = rmb->generic_container;
11944 g_assert (container);
11946 container->type_argc = count;
11947 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11948 container->owner.method = m;
11949 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11951 m->is_generic = TRUE;
11952 mono_method_set_generic_container (m, container);
11954 for (i = 0; i < count; i++) {
11955 MonoReflectionGenericParam *gp =
11956 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11957 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
11958 mono_error_assert_ok (error);
11959 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11960 container->type_params [i] = *param;
11964 * The method signature might have pointers to generic parameters that belong to other methods.
11965 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11966 * generic parameters.
11968 for (i = 0; i < m->signature->param_count; ++i) {
11969 MonoType *t = m->signature->params [i];
11970 if (t->type == MONO_TYPE_MVAR) {
11971 MonoGenericParam *gparam = t->data.generic_param;
11972 if (gparam->num < count) {
11973 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11974 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11980 if (klass->generic_container) {
11981 container->parent = klass->generic_container;
11982 container->context.class_inst = klass->generic_container->context.class_inst;
11984 container->context.method_inst = mono_get_shared_generic_inst (container);
11988 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11992 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11994 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11995 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11996 for (i = 0; i < rmb->nrefs; ++i)
11997 data [i + 1] = rmb->refs [i];
12002 /* Parameter info */
12005 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12006 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12007 for (i = 0; i <= m->signature->param_count; ++i) {
12008 MonoReflectionParamBuilder *pb;
12009 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12010 if ((i > 0) && (pb->attrs)) {
12011 /* Make a copy since it might point to a shared type structure */
12012 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12013 m->signature->params [i - 1]->attrs = pb->attrs;
12016 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12017 MonoDynamicImage *assembly;
12019 MonoTypeEnum def_type;
12023 if (!method_aux->param_defaults) {
12024 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12025 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12027 assembly = (MonoDynamicImage*)klass->image;
12028 idx = encode_constant (assembly, pb->def_value, &def_type);
12029 /* Copy the data from the blob since it might get realloc-ed */
12030 p = assembly->blob.data + idx;
12031 len = mono_metadata_decode_blob_size (p, &p2);
12033 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12034 method_aux->param_default_types [i] = def_type;
12035 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12039 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12040 mono_error_assert_ok (error);
12043 if (!method_aux->param_cattr)
12044 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12045 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12051 /* Parameter marshalling */
12054 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12055 MonoReflectionParamBuilder *pb;
12056 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12057 if (pb->marshal_info) {
12059 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12060 specs [pb->position] =
12061 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12062 if (!is_ok (error)) {
12063 mono_loader_unlock ();
12064 image_g_free (image, specs);
12065 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12071 if (specs != NULL) {
12073 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12074 method_aux->param_marshall = specs;
12077 if (image_is_dynamic (klass->image) && method_aux)
12078 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12080 mono_loader_unlock ();
12086 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12088 ReflectionMethodBuilder rmb;
12089 MonoMethodSignature *sig;
12091 mono_loader_lock ();
12092 g_assert (klass->image != NULL);
12093 sig = ctor_builder_to_signature (klass->image, mb, error);
12094 mono_loader_unlock ();
12095 return_val_if_nok (error, NULL);
12097 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12100 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12101 return_val_if_nok (error, NULL);
12102 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12104 /* If we are in a generic class, we might be called multiple times from inflate_method */
12105 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12106 /* ilgen is no longer needed */
12110 return mb->mhandle;
12114 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12116 ReflectionMethodBuilder rmb;
12117 MonoMethodSignature *sig;
12119 mono_error_init (error);
12121 mono_loader_lock ();
12122 g_assert (klass->image != NULL);
12123 sig = method_builder_to_signature (klass->image, mb, error);
12124 mono_loader_unlock ();
12125 return_val_if_nok (error, NULL);
12127 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12130 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12131 return_val_if_nok (error, NULL);
12132 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12134 /* If we are in a generic class, we might be called multiple times from inflate_method */
12135 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12136 /* ilgen is no longer needed */
12139 return mb->mhandle;
12142 static MonoClassField*
12143 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12145 MonoClassField *field;
12148 mono_error_init (error);
12150 field = g_new0 (MonoClassField, 1);
12152 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12153 mono_error_assert_ok (error);
12154 if (fb->attrs || fb->modreq || fb->modopt) {
12155 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12156 if (!is_ok (error)) {
12160 field->type = mono_metadata_type_dup (NULL, type);
12161 field->type->attrs = fb->attrs;
12163 g_assert (image_is_dynamic (klass->image));
12164 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12165 g_free (field->type);
12166 if (!is_ok (error)) {
12170 field->type = mono_metadata_type_dup (klass->image, custom);
12173 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12174 if (!is_ok (error)) {
12179 if (fb->offset != -1)
12180 field->offset = fb->offset;
12181 field->parent = klass;
12182 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12184 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12191 * mono_reflection_bind_generic_parameters:
12192 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12193 * @type_args: the number of type arguments to bind
12194 * @types: array of type arguments
12195 * @error: set on error
12197 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12198 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12201 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12204 MonoReflectionTypeBuilder *tb = NULL;
12205 gboolean is_dynamic = FALSE;
12206 MonoClass *geninst;
12208 mono_error_init (error);
12210 mono_loader_lock ();
12212 if (is_sre_type_builder (mono_object_class (type))) {
12213 tb = (MonoReflectionTypeBuilder *) type;
12216 } else if (is_sre_generic_instance (mono_object_class (type))) {
12217 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12218 MonoReflectionType *gtd = rgi->generic_type;
12220 if (is_sre_type_builder (mono_object_class (gtd))) {
12221 tb = (MonoReflectionTypeBuilder *)gtd;
12226 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12227 if (tb && tb->generic_container) {
12228 if (!mono_reflection_create_generic_class (tb, error)) {
12229 mono_loader_unlock ();
12234 MonoType *t = mono_reflection_type_get_handle (type, error);
12235 if (!is_ok (error)) {
12236 mono_loader_unlock ();
12240 klass = mono_class_from_mono_type (t);
12241 if (!klass->generic_container) {
12242 mono_loader_unlock ();
12243 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12247 if (klass->wastypebuilder) {
12248 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12253 mono_loader_unlock ();
12255 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12257 return &geninst->byval_arg;
12261 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12263 MonoGenericClass *gclass;
12264 MonoGenericInst *inst;
12266 g_assert (klass->generic_container);
12268 inst = mono_metadata_get_generic_inst (type_argc, types);
12269 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12271 return mono_generic_class_get_class (gclass);
12274 static MonoReflectionMethod*
12275 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12278 MonoMethod *method, *inflated;
12279 MonoMethodInflated *imethod;
12280 MonoGenericContext tmp_context;
12281 MonoGenericInst *ginst;
12282 MonoType **type_argv;
12285 mono_error_init (error);
12287 /*FIXME but this no longer should happen*/
12288 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12289 #ifndef DISABLE_REFLECTION_EMIT
12290 MonoReflectionMethodBuilder *mb = NULL;
12294 mb = (MonoReflectionMethodBuilder *) rmethod;
12295 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12296 return_val_if_nok (error, NULL);
12297 klass = mono_class_from_mono_type (tb);
12299 method = methodbuilder_to_mono_method (klass, mb, error);
12300 return_val_if_nok (error, NULL);
12302 g_assert_not_reached ();
12306 method = rmethod->method;
12309 klass = method->klass;
12311 if (method->is_inflated)
12312 method = ((MonoMethodInflated *) method)->declaring;
12314 count = mono_method_signature (method)->generic_param_count;
12315 if (count != mono_array_length (types))
12318 type_argv = g_new0 (MonoType *, count);
12319 for (i = 0; i < count; i++) {
12320 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12321 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12322 if (!is_ok (error)) {
12323 g_free (type_argv);
12327 ginst = mono_metadata_get_generic_inst (count, type_argv);
12328 g_free (type_argv);
12330 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12331 tmp_context.method_inst = ginst;
12333 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12334 mono_error_assert_ok (error);
12335 imethod = (MonoMethodInflated *) inflated;
12337 /*FIXME but I think this is no longer necessary*/
12338 if (image_is_dynamic (method->klass->image)) {
12339 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12341 * This table maps metadata structures representing inflated methods/fields
12342 * to the reflection objects representing their generic definitions.
12344 mono_image_lock ((MonoImage*)image);
12345 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12346 mono_image_unlock ((MonoImage*)image);
12349 if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12350 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12354 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12358 MonoReflectionMethod*
12359 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12362 MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12363 mono_error_set_pending_exception (&error);
12368 #ifndef DISABLE_REFLECTION_EMIT
12370 static MonoMethod *
12371 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12373 MonoMethodInflated *imethod;
12374 MonoGenericContext *context;
12378 * With generic code sharing the klass might not be inflated.
12379 * This can happen because classes inflated with their own
12380 * type arguments are "normalized" to the uninflated class.
12382 if (!klass->generic_class)
12385 context = mono_class_get_context (klass);
12387 if (klass->method.count && klass->methods) {
12388 /* Find the already created inflated method */
12389 for (i = 0; i < klass->method.count; ++i) {
12390 g_assert (klass->methods [i]->is_inflated);
12391 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12394 g_assert (i < klass->method.count);
12395 imethod = (MonoMethodInflated*)klass->methods [i];
12398 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12399 mono_error_assert_ok (&error);
12402 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12403 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12405 mono_image_lock ((MonoImage*)image);
12406 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12407 mono_image_unlock ((MonoImage*)image);
12409 return (MonoMethod *) imethod;
12412 static MonoMethod *
12413 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12415 MonoMethod *method;
12418 mono_error_init (error);
12420 MonoClass *type_class = mono_object_class (type);
12422 if (is_sre_generic_instance (type_class)) {
12423 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12424 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12425 return_val_if_nok (error, NULL);
12426 gklass = mono_class_from_mono_type (generic_type);
12427 } else if (is_sre_type_builder (type_class)) {
12428 MonoType *t = mono_reflection_type_get_handle (type, error);
12429 return_val_if_nok (error, NULL);
12430 gklass = mono_class_from_mono_type (t);
12431 } else if (type->type) {
12432 gklass = mono_class_from_mono_type (type->type);
12433 gklass = mono_class_get_generic_type_definition (gklass);
12435 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12438 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12439 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12440 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12442 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12446 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12447 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12450 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12451 method = ((MonoReflectionMethod *) obj)->method;
12453 method = NULL; /* prevent compiler warning */
12454 g_error ("can't handle type %s", obj->vtable->klass->name);
12457 MonoType *t = mono_reflection_type_get_handle (type, error);
12458 return_val_if_nok (error, NULL);
12459 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12462 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12464 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12466 MonoGenericClass *gclass;
12467 MonoDynamicGenericClass *dgclass;
12468 MonoClass *klass, *gklass;
12472 mono_error_init (error);
12474 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12475 return_val_if_nok (error, FALSE);
12476 klass = mono_class_from_mono_type (gtype);
12477 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12478 gclass = gtype->data.generic_class;
12480 if (!gclass->is_dynamic)
12483 dgclass = (MonoDynamicGenericClass *) gclass;
12485 if (dgclass->initialized)
12488 gklass = gclass->container_class;
12489 mono_class_init (gklass);
12491 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12493 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12494 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12495 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12497 for (i = 0; i < dgclass->count_fields; i++) {
12498 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12499 MonoClassField *field, *inflated_field = NULL;
12501 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12502 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12503 return_val_if_nok (error, FALSE);
12504 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12505 field = ((MonoReflectionField *) obj)->field;
12507 field = NULL; /* prevent compiler warning */
12508 g_assert_not_reached ();
12511 dgclass->fields [i] = *field;
12512 dgclass->fields [i].parent = klass;
12513 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12514 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12515 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12516 dgclass->field_generic_types [i] = field->type;
12517 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12518 dgclass->field_objects [i] = obj;
12520 if (inflated_field) {
12521 g_free (inflated_field);
12523 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12527 dgclass->initialized = TRUE;
12532 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12535 (void) reflection_generic_class_initialize (type, fields, &error);
12536 mono_error_set_pending_exception (&error);
12540 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12542 MonoDynamicGenericClass *dgclass;
12545 g_assert (gclass->is_dynamic);
12547 dgclass = (MonoDynamicGenericClass *)gclass;
12549 for (i = 0; i < dgclass->count_fields; ++i) {
12550 MonoClassField *field = dgclass->fields + i;
12551 mono_metadata_free_type (field->type);
12552 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12557 * fix_partial_generic_class:
12558 * @klass: a generic instantiation MonoClass
12559 * @error: set on error
12561 * Assumes that the generic container of @klass has its vtable
12562 * initialized, and updates the parent class, insterfaces, methods and
12563 * fields of @klass by inflating the types using the generic context.
12565 * On success returns TRUE, on failure returns FALSE and sets @error.
12569 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12571 MonoClass *gklass = klass->generic_class->container_class;
12572 MonoDynamicGenericClass *dgclass;
12575 mono_error_init (error);
12577 if (klass->wastypebuilder)
12580 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12581 if (klass->parent != gklass->parent) {
12582 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12583 if (mono_error_ok (error)) {
12584 MonoClass *parent = mono_class_from_mono_type (parent_type);
12585 mono_metadata_free_type (parent_type);
12586 if (parent != klass->parent) {
12587 /*fool mono_class_setup_parent*/
12588 klass->supertypes = NULL;
12589 mono_class_setup_parent (klass, parent);
12592 if (gklass->wastypebuilder)
12593 klass->wastypebuilder = TRUE;
12598 if (!dgclass->initialized)
12601 if (klass->method.count != gklass->method.count) {
12602 klass->method.count = gklass->method.count;
12603 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12605 for (i = 0; i < klass->method.count; i++) {
12606 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12607 gklass->methods [i], klass, mono_class_get_context (klass), error);
12608 mono_error_assert_ok (error);
12612 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12613 klass->interface_count = gklass->interface_count;
12614 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12615 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12617 for (i = 0; i < gklass->interface_count; ++i) {
12618 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12619 return_val_if_nok (error, FALSE);
12621 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12622 mono_metadata_free_type (iface_type);
12624 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12627 klass->interfaces_inited = 1;
12630 if (klass->field.count != gklass->field.count) {
12631 klass->field.count = gklass->field.count;
12632 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12634 for (i = 0; i < klass->field.count; i++) {
12635 klass->fields [i] = gklass->fields [i];
12636 klass->fields [i].parent = klass;
12637 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12638 return_val_if_nok (error, FALSE);
12642 /*We can only finish with this klass once it's parent has as well*/
12643 if (gklass->wastypebuilder)
12644 klass->wastypebuilder = TRUE;
12649 * ensure_generic_class_runtime_vtable:
12650 * @klass a generic class
12651 * @error set on error
12653 * Ensures that the generic container of @klass has a vtable and
12654 * returns TRUE on success. On error returns FALSE and sets @error.
12657 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12659 MonoClass *gklass = klass->generic_class->container_class;
12661 mono_error_init (error);
12663 if (!ensure_runtime_vtable (gklass, error))
12666 return fix_partial_generic_class (klass, error);
12670 * ensure_runtime_vtable:
12672 * @error set on error
12674 * Ensures that @klass has a vtable and returns TRUE on success. On
12675 * error returns FALSE and sets @error.
12678 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12680 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12683 mono_error_init (error);
12685 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12688 if (!ensure_runtime_vtable (klass->parent, error))
12692 num = tb->ctors? mono_array_length (tb->ctors): 0;
12693 num += tb->num_methods;
12694 klass->method.count = num;
12695 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12696 num = tb->ctors? mono_array_length (tb->ctors): 0;
12697 for (i = 0; i < num; ++i) {
12698 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12701 klass->methods [i] = ctor;
12703 num = tb->num_methods;
12705 for (i = 0; i < num; ++i) {
12706 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12709 klass->methods [j++] = meth;
12712 if (tb->interfaces) {
12713 klass->interface_count = mono_array_length (tb->interfaces);
12714 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12715 for (i = 0; i < klass->interface_count; ++i) {
12716 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12717 return_val_if_nok (error, FALSE);
12718 klass->interfaces [i] = mono_class_from_mono_type (iface);
12719 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12722 klass->interfaces_inited = 1;
12724 } else if (klass->generic_class){
12725 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12726 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12731 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12733 for (i = 0; i < klass->method.count; ++i) {
12734 MonoMethod *im = klass->methods [i];
12735 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12736 im->slot = slot_num++;
12739 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12740 mono_class_setup_interface_offsets (klass);
12741 mono_class_setup_interface_id (klass);
12745 * The generic vtable is needed even if image->run is not set since some
12746 * runtime code like ves_icall_Type_GetMethodsByName depends on
12747 * method->slot being defined.
12751 * tb->methods could not be freed since it is used for determining
12752 * overrides during dynamic vtable construction.
12759 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12761 mono_error_init (error);
12762 MonoClass *klass = mono_object_class (method);
12763 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12764 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12765 return sr_method->method;
12767 if (is_sre_method_builder (klass)) {
12768 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12769 return mb->mhandle;
12771 if (is_sre_method_on_tb_inst (klass)) {
12772 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12773 MonoMethod *result;
12774 /*FIXME move this to a proper method and unify with resolve_object*/
12775 if (m->method_args) {
12776 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12778 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12779 return_val_if_nok (error, NULL);
12780 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12781 MonoMethod *mono_method;
12783 if (is_sre_method_builder (mono_object_class (m->mb)))
12784 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12785 else if (is_sr_mono_method (mono_object_class (m->mb)))
12786 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12788 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)));
12790 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12795 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12800 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12802 MonoReflectionTypeBuilder *tb;
12804 MonoReflectionMethod *m;
12806 mono_error_init (error);
12808 *num_overrides = 0;
12810 g_assert (image_is_dynamic (klass->image));
12812 if (!mono_class_get_ref_info (klass))
12815 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12817 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12821 for (i = 0; i < tb->num_methods; ++i) {
12822 MonoReflectionMethodBuilder *mb =
12823 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12824 if (mb->override_methods)
12825 onum += mono_array_length (mb->override_methods);
12830 *overrides = g_new0 (MonoMethod*, onum * 2);
12833 for (i = 0; i < tb->num_methods; ++i) {
12834 MonoReflectionMethodBuilder *mb =
12835 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12836 if (mb->override_methods) {
12837 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12838 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12840 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12841 return_if_nok (error);
12842 (*overrides) [onum * 2 + 1] = mb->mhandle;
12844 g_assert (mb->mhandle);
12852 *num_overrides = onum;
12856 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12858 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12859 MonoReflectionFieldBuilder *fb;
12860 MonoClassField *field;
12861 MonoImage *image = klass->image;
12862 const char *p, *p2;
12864 guint32 len, idx, real_size = 0;
12866 klass->field.count = tb->num_fields;
12867 klass->field.first = 0;
12869 mono_error_init (error);
12871 if (tb->class_size) {
12872 if ((tb->packing_size & 0xffffff00) != 0) {
12873 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12874 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12877 klass->packing_size = tb->packing_size;
12878 real_size = klass->instance_size + tb->class_size;
12881 if (!klass->field.count) {
12882 klass->instance_size = MAX (klass->instance_size, real_size);
12886 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12887 mono_class_alloc_ext (klass);
12888 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12890 This is, guess what, a hack.
12891 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12892 On the static path no field class is resolved, only types are built. This is the right thing to do
12894 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12896 klass->size_inited = 1;
12898 for (i = 0; i < klass->field.count; ++i) {
12899 MonoArray *rva_data;
12900 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12901 field = &klass->fields [i];
12902 field->name = mono_string_to_utf8_image (image, fb->name, error);
12903 if (!mono_error_ok (error))
12906 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12907 return_if_nok (error);
12908 field->type = mono_metadata_type_dup (klass->image, type);
12909 field->type->attrs = fb->attrs;
12911 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12912 return_if_nok (error);
12915 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12916 char *base = mono_array_addr (rva_data, char, 0);
12917 size_t size = mono_array_length (rva_data);
12918 char *data = (char *)mono_image_alloc (klass->image, size);
12919 memcpy (data, base, size);
12920 klass->ext->field_def_values [i].data = data;
12922 if (fb->offset != -1)
12923 field->offset = fb->offset;
12924 field->parent = klass;
12925 fb->handle = field;
12926 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12928 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12929 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12931 if (fb->def_value) {
12932 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12933 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12934 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12935 /* Copy the data from the blob since it might get realloc-ed */
12936 p = assembly->blob.data + idx;
12937 len = mono_metadata_decode_blob_size (p, &p2);
12939 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12940 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12944 klass->instance_size = MAX (klass->instance_size, real_size);
12945 mono_class_layout_fields (klass, klass->instance_size);
12949 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12951 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12952 MonoReflectionPropertyBuilder *pb;
12953 MonoImage *image = klass->image;
12954 MonoProperty *properties;
12957 mono_error_init (error);
12960 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12962 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12963 klass->ext->property.first = 0;
12965 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12966 klass->ext->properties = properties;
12967 for (i = 0; i < klass->ext->property.count; ++i) {
12968 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12969 properties [i].parent = klass;
12970 properties [i].attrs = pb->attrs;
12971 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12972 if (!mono_error_ok (error))
12974 if (pb->get_method)
12975 properties [i].get = pb->get_method->mhandle;
12976 if (pb->set_method)
12977 properties [i].set = pb->set_method->mhandle;
12979 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12980 if (pb->def_value) {
12982 const char *p, *p2;
12983 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12984 if (!klass->ext->prop_def_values)
12985 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12986 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12987 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12988 /* Copy the data from the blob since it might get realloc-ed */
12989 p = assembly->blob.data + idx;
12990 len = mono_metadata_decode_blob_size (p, &p2);
12992 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12993 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12998 static MonoReflectionEvent *
12999 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13001 mono_error_init (error);
13003 MonoEvent *event = g_new0 (MonoEvent, 1);
13006 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13007 if (!is_ok (error)) {
13011 klass = mono_class_from_mono_type (type);
13013 event->parent = klass;
13014 event->attrs = eb->attrs;
13015 event->name = mono_string_to_utf8 (eb->name);
13016 if (eb->add_method)
13017 event->add = eb->add_method->mhandle;
13018 if (eb->remove_method)
13019 event->remove = eb->remove_method->mhandle;
13020 if (eb->raise_method)
13021 event->raise = eb->raise_method->mhandle;
13023 #ifndef MONO_SMALL_CONFIG
13024 if (eb->other_methods) {
13026 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13027 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13028 MonoReflectionMethodBuilder *mb =
13029 mono_array_get (eb->other_methods,
13030 MonoReflectionMethodBuilder*, j);
13031 event->other [j] = mb->mhandle;
13036 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13037 if (!is_ok (error)) {
13038 #ifndef MONO_SMALL_CONFIG
13039 g_free (event->other);
13047 MonoReflectionEvent *
13048 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13051 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13052 mono_error_set_pending_exception (&error);
13057 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13059 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13060 MonoReflectionEventBuilder *eb;
13061 MonoImage *image = klass->image;
13065 mono_error_init (error);
13068 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13070 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13071 klass->ext->event.first = 0;
13073 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13074 klass->ext->events = events;
13075 for (i = 0; i < klass->ext->event.count; ++i) {
13076 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13077 events [i].parent = klass;
13078 events [i].attrs = eb->attrs;
13079 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13080 if (!mono_error_ok (error))
13082 if (eb->add_method)
13083 events [i].add = eb->add_method->mhandle;
13084 if (eb->remove_method)
13085 events [i].remove = eb->remove_method->mhandle;
13086 if (eb->raise_method)
13087 events [i].raise = eb->raise_method->mhandle;
13089 #ifndef MONO_SMALL_CONFIG
13090 if (eb->other_methods) {
13092 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13093 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13094 MonoReflectionMethodBuilder *mb =
13095 mono_array_get (eb->other_methods,
13096 MonoReflectionMethodBuilder*, j);
13097 events [i].other [j] = mb->mhandle;
13101 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13105 struct remove_instantiations_user_data
13112 remove_instantiations_of_and_ensure_contents (gpointer key,
13114 gpointer user_data)
13116 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13117 MonoType *type = (MonoType*)key;
13118 MonoClass *klass = data->klass;
13119 gboolean already_failed = !is_ok (data->error);
13121 MonoError *error = already_failed ? &lerror : data->error;
13123 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13124 MonoClass *inst_klass = mono_class_from_mono_type (type);
13125 //Ensure it's safe to use it.
13126 if (!fix_partial_generic_class (inst_klass, error)) {
13127 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13128 // Marked the class with failure, but since some other instantiation already failed,
13129 // just report that one, and swallow the error from this one.
13130 if (already_failed)
13131 mono_error_cleanup (error);
13139 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13141 mono_error_init (error);
13147 for (i = 0; i < mono_array_length (arr); ++i) {
13148 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13149 if (!mono_error_ok (error))
13154 MonoReflectionType*
13155 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13159 MonoDomain* domain;
13160 MonoReflectionType* res;
13163 mono_error_init (&error);
13165 domain = mono_object_domain (tb);
13166 klass = mono_class_from_mono_type (tb->type.type);
13169 * Check for user defined Type subclasses.
13171 RESOLVE_TYPE (tb->parent, &error);
13172 if (!is_ok (&error))
13173 goto failure_unlocked;
13174 check_array_for_usertypes (tb->interfaces, &error);
13175 if (!is_ok (&error))
13176 goto failure_unlocked;
13178 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13179 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13181 RESOLVE_TYPE (fb->type, &error);
13182 if (!is_ok (&error))
13183 goto failure_unlocked;
13184 check_array_for_usertypes (fb->modreq, &error);
13185 if (!is_ok (&error))
13186 goto failure_unlocked;
13187 check_array_for_usertypes (fb->modopt, &error);
13188 if (!is_ok (&error))
13189 goto failure_unlocked;
13190 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13191 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13192 if (!is_ok (&error))
13193 goto failure_unlocked;
13199 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13200 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13202 RESOLVE_TYPE (mb->rtype, &error);
13203 if (!is_ok (&error))
13204 goto failure_unlocked;
13205 check_array_for_usertypes (mb->return_modreq, &error);
13206 if (!is_ok (&error))
13207 goto failure_unlocked;
13208 check_array_for_usertypes (mb->return_modopt, &error);
13209 if (!is_ok (&error))
13210 goto failure_unlocked;
13211 check_array_for_usertypes (mb->parameters, &error);
13212 if (!is_ok (&error))
13213 goto failure_unlocked;
13214 if (mb->param_modreq)
13215 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13216 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13217 if (!is_ok (&error))
13218 goto failure_unlocked;
13220 if (mb->param_modopt)
13221 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13222 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13223 if (!is_ok (&error))
13224 goto failure_unlocked;
13230 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13231 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13233 check_array_for_usertypes (mb->parameters, &error);
13234 if (!is_ok (&error))
13235 goto failure_unlocked;
13236 if (mb->param_modreq)
13237 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13238 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13239 if (!is_ok (&error))
13240 goto failure_unlocked;
13242 if (mb->param_modopt)
13243 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13244 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13245 if (!is_ok (&error))
13246 goto failure_unlocked;
13252 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13255 * we need to lock the domain because the lock will be taken inside
13256 * So, we need to keep the locking order correct.
13258 mono_loader_lock ();
13259 mono_domain_lock (domain);
13260 if (klass->wastypebuilder) {
13261 mono_domain_unlock (domain);
13262 mono_loader_unlock ();
13264 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13265 mono_error_set_pending_exception (&error);
13270 * Fields to set in klass:
13271 * the various flags: delegate/unicode/contextbound etc.
13273 klass->flags = tb->attrs;
13274 klass->has_cctor = 1;
13275 klass->has_finalize = 1;
13276 klass->has_finalize_inited = 1;
13278 mono_class_setup_parent (klass, klass->parent);
13279 /* fool mono_class_setup_supertypes */
13280 klass->supertypes = NULL;
13281 mono_class_setup_supertypes (klass);
13282 mono_class_setup_mono_type (klass);
13285 if (!((MonoDynamicImage*)klass->image)->run) {
13286 if (klass->generic_container) {
13287 /* FIXME: The code below can't handle generic classes */
13288 klass->wastypebuilder = TRUE;
13289 mono_loader_unlock ();
13290 mono_domain_unlock (domain);
13292 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13293 mono_error_set_pending_exception (&error);
13300 /* enums are done right away */
13301 if (!klass->enumtype)
13302 if (!ensure_runtime_vtable (klass, &error))
13305 if (tb->subtypes) {
13306 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13307 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13308 mono_class_alloc_ext (klass);
13309 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13310 if (!is_ok (&error)) goto failure;
13311 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13315 klass->nested_classes_inited = TRUE;
13317 /* fields and object layout */
13318 if (klass->parent) {
13319 if (!klass->parent->size_inited)
13320 mono_class_init (klass->parent);
13321 klass->instance_size = klass->parent->instance_size;
13322 klass->sizes.class_size = 0;
13323 klass->min_align = klass->parent->min_align;
13324 /* if the type has no fields we won't call the field_setup
13325 * routine which sets up klass->has_references.
13327 klass->has_references |= klass->parent->has_references;
13329 klass->instance_size = sizeof (MonoObject);
13330 klass->min_align = 1;
13333 /* FIXME: handle packing_size and instance_size */
13334 typebuilder_setup_fields (klass, &error);
13335 if (!mono_error_ok (&error))
13337 typebuilder_setup_properties (klass, &error);
13338 if (!mono_error_ok (&error))
13341 typebuilder_setup_events (klass, &error);
13342 if (!mono_error_ok (&error))
13345 klass->wastypebuilder = TRUE;
13348 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13349 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13350 * we want to return normal System.MonoType objects, so clear these out from the cache.
13352 * Together with this we must ensure the contents of all instances to match the created type.
13354 if (domain->type_hash && klass->generic_container) {
13355 struct remove_instantiations_user_data data;
13356 data.klass = klass;
13357 data.error = &error;
13358 mono_error_assert_ok (&error);
13359 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13360 if (!is_ok (&error))
13364 mono_domain_unlock (domain);
13365 mono_loader_unlock ();
13367 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13368 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13369 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13370 goto failure_unlocked;
13373 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13374 if (!is_ok (&error))
13375 goto failure_unlocked;
13377 g_assert (res != (MonoReflectionType*)tb);
13382 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13383 klass->wastypebuilder = TRUE;
13384 mono_domain_unlock (domain);
13385 mono_loader_unlock ();
13387 mono_error_set_pending_exception (&error);
13392 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13394 MonoGenericParamFull *param;
13398 mono_error_init (error);
13400 image = &gparam->tbuilder->module->dynamic_image->image;
13402 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13404 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13405 mono_error_assert_ok (error);
13406 param->param.num = gparam->index;
13408 if (gparam->mbuilder) {
13409 if (!gparam->mbuilder->generic_container) {
13410 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13411 return_val_if_nok (error, FALSE);
13413 MonoClass *klass = mono_class_from_mono_type (tb);
13414 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13415 gparam->mbuilder->generic_container->is_method = TRUE;
13417 * Cannot set owner.method, since the MonoMethod is not created yet.
13418 * Set the image field instead, so type_in_image () works.
13420 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13421 gparam->mbuilder->generic_container->owner.image = klass->image;
13423 param->param.owner = gparam->mbuilder->generic_container;
13424 } else if (gparam->tbuilder) {
13425 if (!gparam->tbuilder->generic_container) {
13426 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13427 return_val_if_nok (error, FALSE);
13428 MonoClass *klass = mono_class_from_mono_type (tb);
13429 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13430 gparam->tbuilder->generic_container->owner.klass = klass;
13432 param->param.owner = gparam->tbuilder->generic_container;
13435 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13437 gparam->type.type = &pklass->byval_arg;
13439 mono_class_set_ref_info (pklass, gparam);
13440 mono_image_append_class_to_reflection_info_set (pklass);
13446 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13449 (void) reflection_initialize_generic_parameter (gparam, &error);
13450 mono_error_set_pending_exception (&error);
13455 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13457 MonoReflectionModuleBuilder *module = sig->module;
13458 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13459 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13464 mono_error_init (error);
13466 check_array_for_usertypes (sig->arguments, error);
13467 return_val_if_nok (error, NULL);
13469 sigbuffer_init (&buf, 32);
13471 sigbuffer_add_value (&buf, 0x07);
13472 sigbuffer_add_value (&buf, na);
13473 if (assembly != NULL){
13474 for (i = 0; i < na; ++i) {
13475 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13476 encode_reflection_type (assembly, type, &buf, error);
13477 if (!is_ok (error)) goto fail;
13481 buflen = buf.p - buf.buf;
13482 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13483 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13484 sigbuffer_free (&buf);
13487 sigbuffer_free (&buf);
13492 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13495 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13496 mono_error_set_pending_exception (&error);
13501 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13503 MonoDynamicImage *assembly = sig->module->dynamic_image;
13504 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13509 mono_error_init (error);
13511 check_array_for_usertypes (sig->arguments, error);
13512 return_val_if_nok (error, NULL);
13514 sigbuffer_init (&buf, 32);
13516 sigbuffer_add_value (&buf, 0x06);
13517 for (i = 0; i < na; ++i) {
13518 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13519 encode_reflection_type (assembly, type, &buf, error);
13520 if (!is_ok (error))
13524 buflen = buf.p - buf.buf;
13525 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13526 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13527 sigbuffer_free (&buf);
13531 sigbuffer_free (&buf);
13536 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13539 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13540 mono_error_set_pending_exception (&error);
13545 MonoMethod *handle;
13546 MonoDomain *domain;
13547 } DynamicMethodReleaseData;
13550 * The runtime automatically clean up those after finalization.
13552 static MonoReferenceQueue *dynamic_method_queue;
13555 free_dynamic_method (void *dynamic_method)
13557 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13558 MonoDomain *domain = data->domain;
13559 MonoMethod *method = data->handle;
13562 mono_domain_lock (domain);
13563 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13564 g_hash_table_remove (domain->method_to_dyn_method, method);
13565 mono_domain_unlock (domain);
13566 g_assert (dis_link);
13567 mono_gchandle_free (dis_link);
13569 mono_runtime_free_method (domain, method);
13574 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13576 MonoReferenceQueue *queue;
13577 MonoMethod *handle;
13578 DynamicMethodReleaseData *release_data;
13579 ReflectionMethodBuilder rmb;
13580 MonoMethodSignature *sig;
13582 MonoDomain *domain;
13586 mono_error_init (error);
13588 if (mono_runtime_is_shutting_down ()) {
13589 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13593 if (!(queue = dynamic_method_queue)) {
13594 mono_loader_lock ();
13595 if (!(queue = dynamic_method_queue))
13596 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13597 mono_loader_unlock ();
13600 sig = dynamic_method_to_signature (mb, error);
13601 return_val_if_nok (error, FALSE);
13603 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13606 * Resolve references.
13609 * Every second entry in the refs array is reserved for storing handle_class,
13610 * which is needed by the ldtoken implementation in the JIT.
13612 rmb.nrefs = mb->nrefs;
13613 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13614 for (i = 0; i < mb->nrefs; i += 2) {
13615 MonoClass *handle_class;
13617 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13619 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13620 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13622 * The referenced DynamicMethod should already be created by the managed
13623 * code, except in the case of circular references. In that case, we store
13624 * method in the refs array, and fix it up later when the referenced
13625 * DynamicMethod is created.
13627 if (method->mhandle) {
13628 ref = method->mhandle;
13630 /* FIXME: GC object stored in unmanaged memory */
13633 /* FIXME: GC object stored in unmanaged memory */
13634 method->referenced_by = g_slist_append (method->referenced_by, mb);
13636 handle_class = mono_defaults.methodhandle_class;
13638 MonoException *ex = NULL;
13639 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13640 if (!is_ok (error)) {
13645 ex = mono_get_exception_type_load (NULL, NULL);
13646 else if (mono_security_core_clr_enabled ())
13647 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13651 mono_error_set_exception_instance (error, ex);
13656 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13657 rmb.refs [i + 1] = handle_class;
13661 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13662 if (!is_ok (error)) {
13666 klass = mono_class_from_mono_type (owner_type);
13668 klass = mono_defaults.object_class;
13671 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13673 return_val_if_nok (error, FALSE);
13675 release_data = g_new (DynamicMethodReleaseData, 1);
13676 release_data->handle = handle;
13677 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13678 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13679 g_free (release_data);
13681 /* Fix up refs entries pointing at us */
13682 for (l = mb->referenced_by; l; l = l->next) {
13683 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13684 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13687 g_assert (method->mhandle);
13689 data = (gpointer*)wrapper->method_data;
13690 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13691 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13692 data [i + 1] = mb->mhandle;
13695 g_slist_free (mb->referenced_by);
13697 /* ilgen is no longer needed */
13700 domain = mono_domain_get ();
13701 mono_domain_lock (domain);
13702 if (!domain->method_to_dyn_method)
13703 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13704 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13705 mono_domain_unlock (domain);
13711 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13714 (void) reflection_create_dynamic_method (mb, &error);
13715 mono_error_set_pending_exception (&error);
13718 #endif /* DISABLE_REFLECTION_EMIT */
13722 * mono_reflection_is_valid_dynamic_token:
13724 * Returns TRUE if token is valid.
13728 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13730 return lookup_dyn_token (image, token) != NULL;
13733 MonoMethodSignature *
13734 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13736 MonoMethodSignature *sig;
13737 g_assert (image_is_dynamic (image));
13739 mono_error_init (error);
13741 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13745 return mono_method_signature_checked (method, error);
13748 #ifndef DISABLE_REFLECTION_EMIT
13751 * mono_reflection_lookup_dynamic_token:
13753 * Finish the Builder object pointed to by TOKEN and return the corresponding
13754 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13755 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13758 * LOCKING: Take the loader lock
13761 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13763 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13767 mono_error_init (error);
13769 obj = lookup_dyn_token (assembly, token);
13772 g_error ("Could not find required dynamic token 0x%08x", token);
13774 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13780 handle_class = &klass;
13781 gpointer result = resolve_object (image, obj, handle_class, context, error);
13786 * ensure_complete_type:
13788 * Ensure that KLASS is completed if it is a dynamic type, or references
13792 ensure_complete_type (MonoClass *klass, MonoError *error)
13794 mono_error_init (error);
13796 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13797 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13799 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13800 return_if_nok (error);
13802 // Asserting here could break a lot of code
13803 //g_assert (klass->wastypebuilder);
13806 if (klass->generic_class) {
13807 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13810 for (i = 0; i < inst->type_argc; ++i) {
13811 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13812 return_if_nok (error);
13818 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13820 gpointer result = NULL;
13822 mono_error_init (error);
13824 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13825 result = mono_string_intern_checked ((MonoString*)obj, error);
13826 return_val_if_nok (error, NULL);
13827 *handle_class = mono_defaults.string_class;
13829 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13830 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13831 return_val_if_nok (error, NULL);
13832 MonoClass *mc = mono_class_from_mono_type (type);
13833 if (!mono_class_init (mc)) {
13834 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13839 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13840 return_val_if_nok (error, NULL);
13842 result = mono_class_from_mono_type (inflated);
13843 mono_metadata_free_type (inflated);
13845 result = mono_class_from_mono_type (type);
13847 *handle_class = mono_defaults.typehandle_class;
13849 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13850 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13851 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13852 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13853 result = ((MonoReflectionMethod*)obj)->method;
13855 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13856 mono_error_assert_ok (error);
13858 *handle_class = mono_defaults.methodhandle_class;
13860 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13861 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13862 result = mb->mhandle;
13864 /* Type is not yet created */
13865 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13867 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13868 return_val_if_nok (error, NULL);
13871 * Hopefully this has been filled in by calling CreateType() on the
13875 * TODO: This won't work if the application finishes another
13876 * TypeBuilder instance instead of this one.
13878 result = mb->mhandle;
13881 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13882 mono_error_assert_ok (error);
13884 *handle_class = mono_defaults.methodhandle_class;
13885 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13886 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13888 result = cb->mhandle;
13890 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13892 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13893 return_val_if_nok (error, NULL);
13894 result = cb->mhandle;
13897 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13898 mono_error_assert_ok (error);
13900 *handle_class = mono_defaults.methodhandle_class;
13901 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13902 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13904 ensure_complete_type (field->parent, error);
13905 return_val_if_nok (error, NULL);
13908 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13909 return_val_if_nok (error, NULL);
13911 MonoClass *klass = mono_class_from_mono_type (inflated);
13912 MonoClassField *inflated_field;
13913 gpointer iter = NULL;
13914 mono_metadata_free_type (inflated);
13915 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13916 if (!strcmp (field->name, inflated_field->name))
13919 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13920 result = inflated_field;
13924 *handle_class = mono_defaults.fieldhandle_class;
13926 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13927 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13928 result = fb->handle;
13931 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13933 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13934 return_val_if_nok (error, NULL);
13935 result = fb->handle;
13938 if (fb->handle && fb->handle->parent->generic_container) {
13939 MonoClass *klass = fb->handle->parent;
13940 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13941 return_val_if_nok (error, NULL);
13943 MonoClass *inflated = mono_class_from_mono_type (type);
13945 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13947 mono_metadata_free_type (type);
13949 *handle_class = mono_defaults.fieldhandle_class;
13950 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13951 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13952 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13953 return_val_if_nok (error, NULL);
13956 klass = type->data.klass;
13957 if (klass->wastypebuilder) {
13958 /* Already created */
13962 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13963 return_val_if_nok (error, NULL);
13964 result = type->data.klass;
13967 *handle_class = mono_defaults.typehandle_class;
13968 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13969 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13970 MonoMethodSignature *sig;
13973 if (helper->arguments)
13974 nargs = mono_array_length (helper->arguments);
13978 sig = mono_metadata_signature_alloc (image, nargs);
13979 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13980 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13982 if (helper->unmanaged_call_conv) { /* unmanaged */
13983 sig->call_convention = helper->unmanaged_call_conv - 1;
13984 sig->pinvoke = TRUE;
13985 } else if (helper->call_conv & 0x02) {
13986 sig->call_convention = MONO_CALL_VARARG;
13988 sig->call_convention = MONO_CALL_DEFAULT;
13991 sig->param_count = nargs;
13992 /* TODO: Copy type ? */
13993 sig->ret = helper->return_type->type;
13994 for (i = 0; i < nargs; ++i) {
13995 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13996 if (!is_ok (error)) {
13997 image_g_free (image, sig);
14003 *handle_class = NULL;
14004 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14005 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14006 /* Already created by the managed code */
14007 g_assert (method->mhandle);
14008 result = method->mhandle;
14009 *handle_class = mono_defaults.methodhandle_class;
14010 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14011 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14012 return_val_if_nok (error, NULL);
14013 type = mono_class_inflate_generic_type_checked (type, context, error);
14014 return_val_if_nok (error, NULL);
14016 result = mono_class_from_mono_type (type);
14017 *handle_class = mono_defaults.typehandle_class;
14019 mono_metadata_free_type (type);
14020 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14021 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14022 return_val_if_nok (error, NULL);
14023 type = mono_class_inflate_generic_type_checked (type, context, error);
14024 return_val_if_nok (error, NULL);
14026 result = mono_class_from_mono_type (type);
14027 *handle_class = mono_defaults.typehandle_class;
14029 mono_metadata_free_type (type);
14030 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14031 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14032 MonoClass *inflated;
14034 MonoClassField *field;
14036 if (is_sre_field_builder (mono_object_class (f->fb)))
14037 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14038 else if (is_sr_mono_field (mono_object_class (f->fb)))
14039 field = ((MonoReflectionField*)f->fb)->field;
14041 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)));
14043 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14044 return_val_if_nok (error, NULL);
14045 type = mono_class_inflate_generic_type_checked (finst, context, error);
14046 return_val_if_nok (error, NULL);
14048 inflated = mono_class_from_mono_type (type);
14050 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14051 ensure_complete_type (field->parent, error);
14052 if (!is_ok (error)) {
14053 mono_metadata_free_type (type);
14058 mono_metadata_free_type (type);
14059 *handle_class = mono_defaults.fieldhandle_class;
14060 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14061 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14062 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14063 return_val_if_nok (error, NULL);
14064 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14065 return_val_if_nok (error, NULL);
14067 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14068 MonoMethod *method;
14070 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14071 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14072 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14073 method = ((MonoReflectionMethod *)c->cb)->method;
14075 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)));
14077 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14078 *handle_class = mono_defaults.methodhandle_class;
14079 mono_metadata_free_type (type);
14080 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14081 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14082 if (m->method_args) {
14083 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14084 return_val_if_nok (error, NULL);
14086 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14087 mono_error_assert_ok (error);
14090 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14091 return_val_if_nok (error, NULL);
14092 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14093 return_val_if_nok (error, NULL);
14095 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14096 MonoMethod *method;
14098 if (is_sre_method_builder (mono_object_class (m->mb)))
14099 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14100 else if (is_sr_mono_method (mono_object_class (m->mb)))
14101 method = ((MonoReflectionMethod *)m->mb)->method;
14103 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)));
14105 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14106 mono_metadata_free_type (type);
14108 *handle_class = mono_defaults.methodhandle_class;
14109 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14110 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14113 MonoMethod *method;
14117 mtype = mono_reflection_type_get_handle (m->parent, error);
14118 return_val_if_nok (error, NULL);
14119 klass = mono_class_from_mono_type (mtype);
14121 /* Find the method */
14123 name = mono_string_to_utf8 (m->name);
14125 while ((method = mono_class_get_methods (klass, &iter))) {
14126 if (!strcmp (method->name, name))
14133 // FIXME: Check parameters/return value etc. match
14136 *handle_class = mono_defaults.methodhandle_class;
14137 } else if (is_sre_array (mono_object_get_class(obj)) ||
14138 is_sre_byref (mono_object_get_class(obj)) ||
14139 is_sre_pointer (mono_object_get_class(obj))) {
14140 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14141 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14142 return_val_if_nok (error, NULL);
14145 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14146 return_val_if_nok (error, NULL);
14148 result = mono_class_from_mono_type (inflated);
14149 mono_metadata_free_type (inflated);
14151 result = mono_class_from_mono_type (type);
14153 *handle_class = mono_defaults.typehandle_class;
14155 g_print ("%s\n", obj->vtable->klass->name);
14156 g_assert_not_reached ();
14161 #else /* DISABLE_REFLECTION_EMIT */
14164 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14166 g_assert_not_reached ();
14171 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14173 g_assert_not_reached ();
14177 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14179 g_assert_not_reached ();
14183 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14185 g_assert_not_reached ();
14190 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14192 g_assert_not_reached ();
14196 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14198 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14202 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14204 g_assert_not_reached ();
14208 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14210 g_assert_not_reached ();
14213 MonoReflectionModule *
14214 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14216 g_assert_not_reached ();
14221 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14223 g_assert_not_reached ();
14228 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14230 g_assert_not_reached ();
14235 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14236 gboolean create_open_instance, gboolean register_token, MonoError *error)
14238 g_assert_not_reached ();
14243 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14248 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14250 g_assert_not_reached ();
14254 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14256 mono_error_init (error);
14258 *num_overrides = 0;
14261 MonoReflectionEvent *
14262 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14264 g_assert_not_reached ();
14268 MonoReflectionType*
14269 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14271 g_assert_not_reached ();
14276 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14278 g_assert_not_reached ();
14282 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14284 g_assert_not_reached ();
14289 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14291 g_assert_not_reached ();
14296 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14301 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14307 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14309 mono_error_init (error);
14316 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14318 g_assert_not_reached ();
14321 #endif /* DISABLE_REFLECTION_EMIT */
14323 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14324 const static guint32 declsec_flags_map[] = {
14325 0x00000000, /* empty */
14326 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14327 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14328 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14329 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14330 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14331 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14332 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14333 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14334 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14335 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14336 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14337 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14338 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14339 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14340 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14341 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14342 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14343 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14347 * Returns flags that includes all available security action associated to the handle.
14348 * @token: metadata token (either for a class or a method)
14349 * @image: image where resides the metadata.
14352 mono_declsec_get_flags (MonoImage *image, guint32 token)
14354 int index = mono_metadata_declsec_from_index (image, token);
14355 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14356 guint32 result = 0;
14360 /* HasSecurity can be present for other, not specially encoded, attributes,
14361 e.g. SuppressUnmanagedCodeSecurityAttribute */
14365 for (i = index; i < t->rows; i++) {
14366 guint32 cols [MONO_DECL_SECURITY_SIZE];
14368 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14369 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14372 action = cols [MONO_DECL_SECURITY_ACTION];
14373 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14374 result |= declsec_flags_map [action];
14376 g_assert_not_reached ();
14383 * Get the security actions (in the form of flags) associated with the specified method.
14385 * @method: The method for which we want the declarative security flags.
14386 * Return the declarative security flags for the method (only).
14388 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14389 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14392 mono_declsec_flags_from_method (MonoMethod *method)
14394 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14395 /* FIXME: No cache (for the moment) */
14396 guint32 idx = mono_method_get_index (method);
14397 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14398 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14399 return mono_declsec_get_flags (method->klass->image, idx);
14405 * Get the security actions (in the form of flags) associated with the specified class.
14407 * @klass: The class for which we want the declarative security flags.
14408 * Return the declarative security flags for the class.
14410 * Note: We cache the flags inside the MonoClass structure as this will get
14411 * called very often (at least for each method).
14414 mono_declsec_flags_from_class (MonoClass *klass)
14416 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14417 if (!klass->ext || !klass->ext->declsec_flags) {
14420 idx = mono_metadata_token_index (klass->type_token);
14421 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14422 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14423 mono_loader_lock ();
14424 mono_class_alloc_ext (klass);
14425 mono_loader_unlock ();
14426 /* we cache the flags on classes */
14427 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14429 return klass->ext->declsec_flags;
14435 * Get the security actions (in the form of flags) associated with the specified assembly.
14437 * @assembly: The assembly for which we want the declarative security flags.
14438 * Return the declarative security flags for the assembly.
14441 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14443 guint32 idx = 1; /* there is only one assembly */
14444 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14445 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14446 return mono_declsec_get_flags (assembly->image, idx);
14451 * Fill actions for the specific index (which may either be an encoded class token or
14452 * an encoded method token) from the metadata image.
14453 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14456 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14457 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14459 MonoBoolean result = FALSE;
14461 guint32 cols [MONO_DECL_SECURITY_SIZE];
14462 int index = mono_metadata_declsec_from_index (image, token);
14465 t = &image->tables [MONO_TABLE_DECLSECURITY];
14466 for (i = index; i < t->rows; i++) {
14467 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14469 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14472 /* if present only replace (class) permissions with method permissions */
14473 /* if empty accept either class or method permissions */
14474 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14475 if (!actions->demand.blob) {
14476 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14477 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14478 actions->demand.blob = (char*) (blob + 2);
14479 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14482 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14483 if (!actions->noncasdemand.blob) {
14484 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14485 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14486 actions->noncasdemand.blob = (char*) (blob + 2);
14487 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14490 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14491 if (!actions->demandchoice.blob) {
14492 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14493 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14494 actions->demandchoice.blob = (char*) (blob + 2);
14495 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14505 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14506 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14508 guint32 idx = mono_metadata_token_index (klass->type_token);
14509 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14510 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14511 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14515 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14516 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14518 guint32 idx = mono_method_get_index (method);
14519 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14520 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14521 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14525 * Collect all actions (that requires to generate code in mini) assigned for
14526 * the specified method.
14527 * Note: Don't use the content of actions if the function return FALSE.
14530 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14532 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14533 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14534 MonoBoolean result = FALSE;
14537 /* quick exit if no declarative security is present in the metadata */
14538 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14541 /* we want the original as the wrapper is "free" of the security informations */
14542 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14543 method = mono_marshal_method_from_wrapper (method);
14548 /* First we look for method-level attributes */
14549 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14550 mono_class_init (method->klass);
14551 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14553 result = mono_declsec_get_method_demands_params (method, demands,
14554 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14557 /* Here we use (or create) the class declarative cache to look for demands */
14558 flags = mono_declsec_flags_from_class (method->klass);
14559 if (flags & mask) {
14561 mono_class_init (method->klass);
14562 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14564 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14565 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14568 /* The boolean return value is used as a shortcut in case nothing needs to
14569 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14575 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14577 * Note: Don't use the content of actions if the function return FALSE.
14580 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14582 MonoBoolean result = FALSE;
14585 /* quick exit if no declarative security is present in the metadata */
14586 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14589 /* we want the original as the wrapper is "free" of the security informations */
14590 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14591 method = mono_marshal_method_from_wrapper (method);
14596 /* results are independant - zeroize both */
14597 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14598 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14600 /* First we look for method-level attributes */
14601 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14602 mono_class_init (method->klass);
14604 result = mono_declsec_get_method_demands_params (method, cmethod,
14605 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14608 /* Here we use (or create) the class declarative cache to look for demands */
14609 flags = mono_declsec_flags_from_class (method->klass);
14610 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14611 mono_class_init (method->klass);
14613 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14614 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14621 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14623 * @klass The inherited class - this is the class that provides the security check (attributes)
14625 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14627 * Note: Don't use the content of actions if the function return FALSE.
14630 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14632 MonoBoolean result = FALSE;
14635 /* quick exit if no declarative security is present in the metadata */
14636 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14639 /* Here we use (or create) the class declarative cache to look for demands */
14640 flags = mono_declsec_flags_from_class (klass);
14641 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14642 mono_class_init (klass);
14643 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14645 result |= mono_declsec_get_class_demands_params (klass, demands,
14646 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14653 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14655 * Note: Don't use the content of actions if the function return FALSE.
14658 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14660 /* quick exit if no declarative security is present in the metadata */
14661 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14664 /* we want the original as the wrapper is "free" of the security informations */
14665 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14666 method = mono_marshal_method_from_wrapper (method);
14671 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14672 mono_class_init (method->klass);
14673 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14675 return mono_declsec_get_method_demands_params (method, demands,
14676 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14683 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14685 guint32 cols [MONO_DECL_SECURITY_SIZE];
14689 int index = mono_metadata_declsec_from_index (image, token);
14693 t = &image->tables [MONO_TABLE_DECLSECURITY];
14694 for (i = index; i < t->rows; i++) {
14695 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14697 /* shortcut - index are ordered */
14698 if (token != cols [MONO_DECL_SECURITY_PARENT])
14701 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14702 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14703 entry->blob = (char*) (metadata + 2);
14704 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14713 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14715 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14716 guint32 idx = mono_method_get_index (method);
14717 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14718 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14719 return get_declsec_action (method->klass->image, idx, action, entry);
14725 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14728 guint32 flags = mono_declsec_flags_from_class (klass);
14729 if (declsec_flags_map [action] & flags) {
14730 guint32 idx = mono_metadata_token_index (klass->type_token);
14731 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14732 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14733 return get_declsec_action (klass->image, idx, action, entry);
14739 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14741 guint32 idx = 1; /* there is only one assembly */
14742 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14743 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14745 return get_declsec_action (assembly->image, idx, action, entry);
14749 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14751 MonoObject *res, *exc;
14753 static MonoMethod *method = NULL;
14755 mono_error_init (error);
14757 if (method == NULL) {
14758 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14763 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14764 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14766 g_assert (mono_class_get_ref_info (klass));
14767 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14769 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14770 return_val_if_nok (error, FALSE);
14772 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14774 if (exc || !mono_error_ok (error)) {
14775 mono_error_cleanup (error);
14778 return *(MonoBoolean*)mono_object_unbox (res);
14782 * mono_reflection_type_get_type:
14783 * @reftype: the System.Type object
14785 * Returns the MonoType* associated with the C# System.Type object @reftype.
14788 mono_reflection_type_get_type (MonoReflectionType *reftype)
14790 g_assert (reftype);
14793 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14794 mono_error_assert_ok (&error);
14799 * mono_reflection_assembly_get_assembly:
14800 * @refassembly: the System.Reflection.Assembly object
14802 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14805 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14807 g_assert (refassembly);
14809 return refassembly->assembly;