2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/mempool-internals.h>
41 #include <mono/metadata/security-core-clr.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-ptr-array.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/checked-build.h>
49 static gboolean is_usertype (MonoReflectionType *ref);
50 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA 0x00002000
65 MonoReflectionILGen *ilgen;
66 MonoReflectionType *rtype;
67 MonoArray *parameters;
68 MonoArray *generic_params;
69 MonoGenericContainer *generic_container;
75 guint32 *table_idx; /* note: it's a pointer */
79 MonoBoolean init_locals;
80 MonoBoolean skip_visibility;
81 MonoArray *return_modreq;
82 MonoArray *return_modopt;
83 MonoArray *param_modreq;
84 MonoArray *param_modopt;
85 MonoArray *permissions;
90 int charset, extra_flags, native_cc;
91 MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
96 MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
109 MONO_INTERFACEIMPL_SIZE,
110 MONO_MEMBERREF_SIZE, /* 0x0A */
112 MONO_CUSTOM_ATTR_SIZE,
113 MONO_FIELD_MARSHAL_SIZE,
114 MONO_DECL_SECURITY_SIZE,
115 MONO_CLASS_LAYOUT_SIZE,
116 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117 MONO_STAND_ALONE_SIGNATURE_SIZE,
121 MONO_PROPERTY_MAP_SIZE,
124 MONO_METHOD_SEMA_SIZE,
125 MONO_METHODIMPL_SIZE,
126 MONO_MODULEREF_SIZE, /* 0x1A */
132 MONO_ASSEMBLY_SIZE, /* 0x20 */
133 MONO_ASSEMBLY_PROCESSOR_SIZE,
134 MONO_ASSEMBLYOS_SIZE,
135 MONO_ASSEMBLYREF_SIZE,
136 MONO_ASSEMBLYREFPROC_SIZE,
137 MONO_ASSEMBLYREFOS_SIZE,
141 MONO_NESTED_CLASS_SIZE,
143 MONO_GENERICPARAM_SIZE, /* 0x2A */
144 MONO_METHODSPEC_SIZE,
145 MONO_GENPARCONSTRAINT_SIZE
149 #ifndef DISABLE_REFLECTION_EMIT
150 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
151 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
152 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
153 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
154 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
155 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
157 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
158 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
159 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
160 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
161 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
167 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
168 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
169 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
170 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
171 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
172 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
173 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
174 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
175 static gboolean is_sre_array (MonoClass *klass);
176 static gboolean is_sre_byref (MonoClass *klass);
177 static gboolean is_sre_pointer (MonoClass *klass);
178 static gboolean is_sre_type_builder (MonoClass *klass);
179 static gboolean is_sre_method_builder (MonoClass *klass);
180 static gboolean is_sre_ctor_builder (MonoClass *klass);
181 static gboolean is_sre_field_builder (MonoClass *klass);
182 static gboolean is_sr_mono_method (MonoClass *klass);
183 static gboolean is_sr_mono_cmethod (MonoClass *klass);
184 static gboolean is_sr_mono_generic_method (MonoClass *klass);
185 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
186 static gboolean is_sr_mono_field (MonoClass *klass);
187 static gboolean is_sr_mono_property (MonoClass *klass);
188 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
189 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
191 static gboolean type_is_reference (MonoType *type);
193 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
194 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
195 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
197 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
198 static void init_type_builder_generics (MonoObject *type, MonoError *error);
200 #define RESOLVE_TYPE(type, error) do { \
201 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
204 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205 __type = mono_reflection_type_resolve_user_types (__type, error); \
206 if (mono_error_ok (error)) \
207 mono_array_set (arr, MonoReflectionType*, index, __type); \
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
250 dynamic_images_lock (void)
252 mono_os_mutex_lock (&dynamic_images_mutex);
256 dynamic_images_unlock (void)
258 mono_os_mutex_unlock (&dynamic_images_mutex);
262 * mono_find_dynamic_image_owner:
264 * Find the dynamic image, if any, which a given pointer is located in the memory of.
267 mono_find_dynamic_image_owner (void *ptr)
269 MonoImage *owner = NULL;
272 dynamic_images_lock ();
276 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278 if (mono_mempool_contains_addr (image->mempool, ptr))
283 dynamic_images_unlock ();
289 mono_reflection_init (void)
291 mono_os_mutex_init (&dynamic_images_mutex);
295 dynamic_image_lock (MonoDynamicImage *image)
298 mono_image_lock ((MonoImage*)image);
303 dynamic_image_unlock (MonoDynamicImage *image)
305 mono_image_unlock ((MonoImage*)image);
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
311 MONO_REQ_GC_UNSAFE_MODE;
313 dynamic_image_lock (assembly);
314 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315 dynamic_image_unlock (assembly);
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
321 MONO_REQ_GC_UNSAFE_MODE;
325 dynamic_image_lock (assembly);
326 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327 dynamic_image_unlock (assembly);
333 sigbuffer_init (SigBuffer *buf, int size)
335 MONO_REQ_GC_NEUTRAL_MODE;
337 buf->buf = (char *)g_malloc (size);
339 buf->end = buf->buf + size;
343 sigbuffer_make_room (SigBuffer *buf, int size)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 if (buf->end - buf->p < size) {
348 int new_size = buf->end - buf->buf + size + 32;
349 char *p = (char *)g_realloc (buf->buf, new_size);
350 size = buf->p - buf->buf;
353 buf->end = buf->buf + new_size;
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
360 MONO_REQ_GC_NEUTRAL_MODE;
362 sigbuffer_make_room (buf, 6);
363 mono_metadata_encode_value (val, buf->p, &buf->p);
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
369 MONO_REQ_GC_NEUTRAL_MODE;
371 sigbuffer_make_room (buf, 1);
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
379 MONO_REQ_GC_NEUTRAL_MODE;
381 sigbuffer_make_room (buf, size);
382 memcpy (buf->p, p, size);
387 sigbuffer_free (SigBuffer *buf)
389 MONO_REQ_GC_NEUTRAL_MODE;
394 #ifndef DISABLE_REFLECTION_EMIT
398 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
402 image_g_malloc (MonoImage *image, guint size)
404 MONO_REQ_GC_NEUTRAL_MODE;
407 return mono_image_alloc (image, size);
409 return g_malloc (size);
411 #endif /* !DISABLE_REFLECTION_EMIT */
416 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
420 image_g_malloc0 (MonoImage *image, guint size)
422 MONO_REQ_GC_NEUTRAL_MODE;
425 return mono_image_alloc0 (image, size);
427 return g_malloc0 (size);
432 * @image: a MonoImage
435 * If @image is NULL, free @ptr, otherwise do nothing.
438 image_g_free (MonoImage *image, gpointer ptr)
444 #ifndef DISABLE_REFLECTION_EMIT
446 image_strdup (MonoImage *image, const char *s)
448 MONO_REQ_GC_NEUTRAL_MODE;
451 return mono_image_strdup (image, s);
457 #define image_g_new(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
460 #define image_g_new0(image,struct_type, n_structs) \
461 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
465 alloc_table (MonoDynamicTable *table, guint nrows)
467 MONO_REQ_GC_NEUTRAL_MODE;
470 g_assert (table->columns);
471 if (nrows + 1 >= table->alloc_rows) {
472 while (nrows + 1 >= table->alloc_rows) {
473 if (table->alloc_rows == 0)
474 table->alloc_rows = 16;
476 table->alloc_rows *= 2;
479 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
484 make_room_in_stream (MonoDynamicStream *stream, int size)
486 MONO_REQ_GC_NEUTRAL_MODE;
488 if (size <= stream->alloc_size)
491 while (stream->alloc_size <= size) {
492 if (stream->alloc_size < 4096)
493 stream->alloc_size = 4096;
495 stream->alloc_size *= 2;
498 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
504 MONO_REQ_GC_NEUTRAL_MODE;
508 gpointer oldkey, oldval;
510 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511 return GPOINTER_TO_UINT (oldval);
513 len = strlen (str) + 1;
516 make_room_in_stream (sh, idx + len);
519 * We strdup the string even if we already copy them in sh->data
520 * so that the string pointers in the hash remain valid even if
521 * we need to realloc sh->data. We may want to avoid that later.
523 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524 memcpy (sh->data + idx, str, len);
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
532 MONO_REQ_GC_UNSAFE_MODE;
535 char *name = mono_string_to_utf8_checked (str, &error);
536 mono_error_raise_exception (&error); /* FIXME don't raise here */
538 idx = string_heap_insert (sh, name);
543 #ifndef DISABLE_REFLECTION_EMIT
545 string_heap_init (MonoDynamicStream *sh)
547 MONO_REQ_GC_NEUTRAL_MODE;
550 sh->alloc_size = 4096;
551 sh->data = (char *)g_malloc (4096);
552 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
553 string_heap_insert (sh, "");
558 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
560 MONO_REQ_GC_NEUTRAL_MODE;
564 make_room_in_stream (stream, stream->index + len);
565 memcpy (stream->data + stream->index, data, len);
567 stream->index += len;
569 * align index? Not without adding an additional param that controls it since
570 * we may store a blob value in pieces.
576 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
578 MONO_REQ_GC_NEUTRAL_MODE;
582 make_room_in_stream (stream, stream->index + len);
583 memset (stream->data + stream->index, 0, len);
585 stream->index += len;
590 stream_data_align (MonoDynamicStream *stream)
592 MONO_REQ_GC_NEUTRAL_MODE;
595 guint32 count = stream->index % 4;
597 /* we assume the stream data will be aligned */
599 mono_image_add_stream_data (stream, buf, 4 - count);
602 #ifndef DISABLE_REFLECTION_EMIT
604 mono_blob_entry_hash (const char* str)
606 MONO_REQ_GC_NEUTRAL_MODE;
610 len = mono_metadata_decode_blob_size (str, &str);
614 for (str += 1; str < end; str++)
615 h = (h << 5) - h + *str;
623 mono_blob_entry_equal (const char *str1, const char *str2) {
624 MONO_REQ_GC_NEUTRAL_MODE;
629 len = mono_metadata_decode_blob_size (str1, &end1);
630 len2 = mono_metadata_decode_blob_size (str2, &end2);
633 return memcmp (end1, end2, len) == 0;
637 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
639 MONO_REQ_GC_NEUTRAL_MODE;
643 gpointer oldkey, oldval;
645 copy = (char *)g_malloc (s1+s2);
646 memcpy (copy, b1, s1);
647 memcpy (copy + s1, b2, s2);
648 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
650 idx = GPOINTER_TO_UINT (oldval);
652 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
653 mono_image_add_stream_data (&assembly->blob, b2, s2);
654 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
660 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
662 MONO_REQ_GC_NEUTRAL_MODE;
666 guint32 size = buf->p - buf->buf;
668 g_assert (size <= (buf->end - buf->buf));
669 mono_metadata_encode_value (size, b, &b);
670 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
674 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
675 * dest may be misaligned.
678 swap_with_size (char *dest, const char* val, int len, int nelem) {
679 MONO_REQ_GC_NEUTRAL_MODE;
680 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
683 for (elem = 0; elem < nelem; ++elem) {
709 g_assert_not_reached ();
715 memcpy (dest, val, len * nelem);
720 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
722 MONO_REQ_GC_UNSAFE_MODE;
726 guint32 idx = 0, len;
728 len = str->length * 2;
729 mono_metadata_encode_value (len, b, &b);
730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
732 char *swapped = g_malloc (2 * mono_string_length (str));
733 const char *p = (const char*)mono_string_chars (str);
735 swap_with_size (swapped, p, 2, mono_string_length (str));
736 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
740 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
745 #ifndef DISABLE_REFLECTION_EMIT
747 default_class_from_mono_type (MonoType *type)
749 MONO_REQ_GC_NEUTRAL_MODE;
751 switch (type->type) {
752 case MONO_TYPE_OBJECT:
753 return mono_defaults.object_class;
755 return mono_defaults.void_class;
756 case MONO_TYPE_BOOLEAN:
757 return mono_defaults.boolean_class;
759 return mono_defaults.char_class;
761 return mono_defaults.sbyte_class;
763 return mono_defaults.byte_class;
765 return mono_defaults.int16_class;
767 return mono_defaults.uint16_class;
769 return mono_defaults.int32_class;
771 return mono_defaults.uint32_class;
773 return mono_defaults.int_class;
775 return mono_defaults.uint_class;
777 return mono_defaults.int64_class;
779 return mono_defaults.uint64_class;
781 return mono_defaults.single_class;
783 return mono_defaults.double_class;
784 case MONO_TYPE_STRING:
785 return mono_defaults.string_class;
787 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
788 g_assert_not_reached ();
796 * mono_class_get_ref_info:
798 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
801 mono_class_get_ref_info (MonoClass *klass)
803 MONO_REQ_GC_UNSAFE_MODE;
805 if (klass->ref_info_handle == 0)
808 return mono_gchandle_get_target (klass->ref_info_handle);
812 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
814 MONO_REQ_GC_UNSAFE_MODE;
816 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
817 g_assert (klass->ref_info_handle != 0);
821 mono_class_free_ref_info (MonoClass *klass)
823 MONO_REQ_GC_NEUTRAL_MODE;
825 if (klass->ref_info_handle) {
826 mono_gchandle_free (klass->ref_info_handle);
827 klass->ref_info_handle = 0;
832 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
834 MONO_REQ_GC_NEUTRAL_MODE;
837 MonoGenericInst *class_inst;
842 class_inst = gclass->context.class_inst;
844 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
845 klass = gclass->container_class;
846 sigbuffer_add_value (buf, klass->byval_arg.type);
847 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
849 sigbuffer_add_value (buf, class_inst->type_argc);
850 for (i = 0; i < class_inst->type_argc; ++i)
851 encode_type (assembly, class_inst->type_argv [i], buf);
856 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
858 MONO_REQ_GC_NEUTRAL_MODE;
861 g_assert_not_reached ();
866 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
870 case MONO_TYPE_BOOLEAN:
884 case MONO_TYPE_STRING:
885 case MONO_TYPE_OBJECT:
886 case MONO_TYPE_TYPEDBYREF:
887 sigbuffer_add_value (buf, type->type);
890 sigbuffer_add_value (buf, type->type);
891 encode_type (assembly, type->data.type, buf);
893 case MONO_TYPE_SZARRAY:
894 sigbuffer_add_value (buf, type->type);
895 encode_type (assembly, &type->data.klass->byval_arg, buf);
897 case MONO_TYPE_VALUETYPE:
898 case MONO_TYPE_CLASS: {
899 MonoClass *k = mono_class_from_mono_type (type);
901 if (k->generic_container) {
902 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
903 encode_generic_class (assembly, gclass, buf);
906 * Make sure we use the correct type.
908 sigbuffer_add_value (buf, k->byval_arg.type);
910 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
911 * otherwise two typerefs could point to the same type, leading to
912 * verification errors.
914 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
918 case MONO_TYPE_ARRAY:
919 sigbuffer_add_value (buf, type->type);
920 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
921 sigbuffer_add_value (buf, type->data.array->rank);
922 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
923 sigbuffer_add_value (buf, 0);
925 case MONO_TYPE_GENERICINST:
926 encode_generic_class (assembly, type->data.generic_class, buf);
930 sigbuffer_add_value (buf, type->type);
931 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
934 g_error ("need to encode type %x", type->type);
939 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
941 MONO_REQ_GC_UNSAFE_MODE;
943 mono_error_init (error);
946 sigbuffer_add_value (buf, MONO_TYPE_VOID);
950 MonoType *t = mono_reflection_type_get_handle (type, error);
951 return_if_nok (error);
952 encode_type (assembly, t, buf);
956 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
958 MONO_REQ_GC_UNSAFE_MODE;
962 mono_error_init (error);
965 for (i = 0; i < mono_array_length (modreq); ++i) {
966 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
967 return_if_nok (error);
968 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
969 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
973 for (i = 0; i < mono_array_length (modopt); ++i) {
974 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
975 return_if_nok (error);
976 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
977 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
982 #ifndef DISABLE_REFLECTION_EMIT
984 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
986 MONO_REQ_GC_UNSAFE_MODE;
990 guint32 nparams = sig->param_count;
996 sigbuffer_init (&buf, 32);
998 * FIXME: vararg, explicit_this, differenc call_conv values...
1000 idx = sig->call_convention;
1002 idx |= 0x20; /* hasthis */
1003 if (sig->generic_param_count)
1004 idx |= 0x10; /* generic */
1005 sigbuffer_add_byte (&buf, idx);
1006 if (sig->generic_param_count)
1007 sigbuffer_add_value (&buf, sig->generic_param_count);
1008 sigbuffer_add_value (&buf, nparams);
1009 encode_type (assembly, sig->ret, &buf);
1010 for (i = 0; i < nparams; ++i) {
1011 if (i == sig->sentinelpos)
1012 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1013 encode_type (assembly, sig->params [i], &buf);
1015 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1016 sigbuffer_free (&buf);
1022 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1024 MONO_REQ_GC_UNSAFE_MODE;
1026 mono_error_init (error);
1029 * FIXME: reuse code from method_encode_signature().
1033 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1034 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1035 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1038 sigbuffer_init (&buf, 32);
1039 /* LAMESPEC: all the call conv spec is foobared */
1040 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1041 if (mb->call_conv & 2)
1042 idx |= 0x5; /* vararg */
1043 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1044 idx |= 0x20; /* hasthis */
1046 idx |= 0x10; /* generic */
1047 sigbuffer_add_byte (&buf, idx);
1049 sigbuffer_add_value (&buf, ngparams);
1050 sigbuffer_add_value (&buf, nparams + notypes);
1051 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1054 encode_reflection_type (assembly, mb->rtype, &buf, error);
1057 for (i = 0; i < nparams; ++i) {
1058 MonoArray *modreq = NULL;
1059 MonoArray *modopt = NULL;
1060 MonoReflectionType *pt;
1062 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1063 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1064 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1065 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1066 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1069 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1070 encode_reflection_type (assembly, pt, &buf, error);
1075 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1076 for (i = 0; i < notypes; ++i) {
1077 MonoReflectionType *pt;
1079 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1080 encode_reflection_type (assembly, pt, &buf, error);
1085 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1087 sigbuffer_free (&buf);
1092 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1094 MONO_REQ_GC_UNSAFE_MODE;
1096 mono_error_init (error);
1098 MonoDynamicTable *table;
1100 guint32 idx, sig_idx;
1101 guint nl = mono_array_length (ilgen->locals);
1105 sigbuffer_init (&buf, 32);
1106 sigbuffer_add_value (&buf, 0x07);
1107 sigbuffer_add_value (&buf, nl);
1108 for (i = 0; i < nl; ++i) {
1109 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1112 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1114 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1115 if (!is_ok (error)) {
1116 sigbuffer_free (&buf);
1120 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1121 sigbuffer_free (&buf);
1123 if (assembly->standalonesig_cache == NULL)
1124 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1125 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1129 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1130 idx = table->next_idx ++;
1132 alloc_table (table, table->rows);
1133 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1135 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1137 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1143 method_count_clauses (MonoReflectionILGen *ilgen)
1145 MONO_REQ_GC_UNSAFE_MODE;
1147 guint32 num_clauses = 0;
1150 MonoILExceptionInfo *ex_info;
1151 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1152 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1153 if (ex_info->handlers)
1154 num_clauses += mono_array_length (ex_info->handlers);
1162 #ifndef DISABLE_REFLECTION_EMIT
1163 static MonoExceptionClause*
1164 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1166 MONO_REQ_GC_UNSAFE_MODE;
1168 mono_error_init (error);
1170 MonoExceptionClause *clauses;
1171 MonoExceptionClause *clause;
1172 MonoILExceptionInfo *ex_info;
1173 MonoILExceptionBlock *ex_block;
1174 guint32 finally_start;
1175 int i, j, clause_index;;
1177 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1180 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1181 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1182 finally_start = ex_info->start + ex_info->len;
1183 if (!ex_info->handlers)
1185 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1186 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1187 clause = &(clauses [clause_index]);
1189 clause->flags = ex_block->type;
1190 clause->try_offset = ex_info->start;
1192 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1193 clause->try_len = finally_start - ex_info->start;
1195 clause->try_len = ex_info->len;
1196 clause->handler_offset = ex_block->start;
1197 clause->handler_len = ex_block->len;
1198 if (ex_block->extype) {
1199 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1201 if (!is_ok (error)) {
1202 image_g_free (image, clauses);
1205 clause->data.catch_class = mono_class_from_mono_type (extype);
1207 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1208 clause->data.filter_offset = ex_block->filter_offset;
1210 clause->data.filter_offset = 0;
1212 finally_start = ex_block->start + ex_block->len;
1220 #endif /* !DISABLE_REFLECTION_EMIT */
1223 * method_encode_code:
1225 * @assembly the assembly
1226 * @mb the managed MethodBuilder
1227 * @error set on error
1229 * Note that the return value is not sensible if @error is set.
1232 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1234 MONO_REQ_GC_UNSAFE_MODE;
1239 gint32 max_stack, i;
1240 gint32 num_locals = 0;
1241 gint32 num_exception = 0;
1244 char fat_header [12];
1246 guint16 short_value;
1247 guint32 local_sig = 0;
1248 guint32 header_size = 12;
1251 mono_error_init (error);
1253 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1254 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1258 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1260 code = mb->ilgen->code;
1261 code_size = mb->ilgen->code_len;
1262 max_stack = mb->ilgen->max_stack;
1263 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1264 if (mb->ilgen->ex_handlers)
1265 num_exception = method_count_clauses (mb->ilgen);
1269 MonoError inner_error;
1270 char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
1271 if (!is_ok (&inner_error)) {
1272 name = g_strdup ("");
1273 mono_error_cleanup (&inner_error);
1275 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1276 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1282 code_size = mono_array_length (code);
1283 max_stack = 8; /* we probably need to run a verifier on the code... */
1286 stream_data_align (&assembly->code);
1288 /* check for exceptions, maxstack, locals */
1289 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1291 if (code_size < 64 && !(code_size & 1)) {
1292 flags = (code_size << 2) | 0x2;
1293 } else if (code_size < 32 && (code_size & 1)) {
1294 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1298 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1299 /* add to the fixup todo list */
1300 if (mb->ilgen && mb->ilgen->num_token_fixups)
1301 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1302 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1303 return assembly->text_rva + idx;
1307 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1308 return_val_if_nok (error, 0);
1311 * FIXME: need to set also the header size in fat_flags.
1312 * (and more sects and init locals flags)
1316 fat_flags |= METHOD_HEADER_MORE_SECTS;
1317 if (mb->init_locals)
1318 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1319 fat_header [0] = fat_flags;
1320 fat_header [1] = (header_size / 4 ) << 4;
1321 short_value = GUINT16_TO_LE (max_stack);
1322 memcpy (fat_header + 2, &short_value, 2);
1323 int_value = GUINT32_TO_LE (code_size);
1324 memcpy (fat_header + 4, &int_value, 4);
1325 int_value = GUINT32_TO_LE (local_sig);
1326 memcpy (fat_header + 8, &int_value, 4);
1327 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1328 /* add to the fixup todo list */
1329 if (mb->ilgen && mb->ilgen->num_token_fixups)
1330 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1332 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1333 if (num_exception) {
1334 unsigned char sheader [4];
1335 MonoILExceptionInfo * ex_info;
1336 MonoILExceptionBlock * ex_block;
1339 stream_data_align (&assembly->code);
1340 /* always use fat format for now */
1341 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1342 num_exception *= 6 * sizeof (guint32);
1343 num_exception += 4; /* include the size of the header */
1344 sheader [1] = num_exception & 0xff;
1345 sheader [2] = (num_exception >> 8) & 0xff;
1346 sheader [3] = (num_exception >> 16) & 0xff;
1347 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1348 /* fat header, so we are already aligned */
1350 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1351 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1352 if (ex_info->handlers) {
1353 int finally_start = ex_info->start + ex_info->len;
1354 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1356 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1358 val = GUINT32_TO_LE (ex_block->type);
1359 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1361 val = GUINT32_TO_LE (ex_info->start);
1362 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1363 /* need fault, too, probably */
1364 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1365 val = GUINT32_TO_LE (finally_start - ex_info->start);
1367 val = GUINT32_TO_LE (ex_info->len);
1368 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1369 /* handler offset */
1370 val = GUINT32_TO_LE (ex_block->start);
1371 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1373 val = GUINT32_TO_LE (ex_block->len);
1374 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1375 finally_start = ex_block->start + ex_block->len;
1376 if (ex_block->extype) {
1377 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1378 return_val_if_nok (error, 0);
1380 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1382 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1383 val = ex_block->filter_offset;
1387 val = GUINT32_TO_LE (val);
1388 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1389 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1390 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1393 g_error ("No clauses for ex info block %d", i);
1397 return assembly->text_rva + idx;
1401 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1403 MONO_REQ_GC_NEUTRAL_MODE;
1406 MonoDynamicTable *table;
1409 table = &assembly->tables [table_idx];
1411 g_assert (col < table->columns);
1413 values = table->values + table->columns;
1414 for (i = 1; i <= table->rows; ++i) {
1415 if (values [col] == token)
1417 values += table->columns;
1423 * LOCKING: Acquires the loader lock.
1425 static MonoCustomAttrInfo*
1426 lookup_custom_attr (MonoImage *image, gpointer member)
1428 MONO_REQ_GC_NEUTRAL_MODE;
1430 MonoCustomAttrInfo* res;
1432 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1437 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1443 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1445 MONO_REQ_GC_UNSAFE_MODE;
1447 /* FIXME: Need to do more checks */
1448 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1449 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1451 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1458 static MonoCustomAttrInfo*
1459 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1461 MONO_REQ_GC_UNSAFE_MODE;
1463 int i, index, count, not_visible;
1464 MonoCustomAttrInfo *ainfo;
1465 MonoReflectionCustomAttr *cattr;
1469 /* FIXME: check in assembly the Run flag is set */
1471 count = mono_array_length (cattrs);
1473 /* Skip nonpublic attributes since MS.NET seems to do the same */
1474 /* FIXME: This needs to be done more globally */
1476 for (i = 0; i < count; ++i) {
1477 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1478 if (!custom_attr_visible (image, cattr))
1481 count -= not_visible;
1483 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1485 ainfo->image = image;
1486 ainfo->num_attrs = count;
1487 ainfo->cached = alloc_img != NULL;
1489 for (i = 0; i < count; ++i) {
1490 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1491 if (custom_attr_visible (image, cattr)) {
1492 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1493 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1494 ainfo->attrs [index].ctor = cattr->ctor->method;
1495 ainfo->attrs [index].data = saved;
1496 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1504 #ifndef DISABLE_REFLECTION_EMIT
1506 * LOCKING: Acquires the loader lock.
1509 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1511 MONO_REQ_GC_UNSAFE_MODE;
1513 MonoCustomAttrInfo *ainfo, *tmp;
1515 if (!cattrs || !mono_array_length (cattrs))
1518 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1520 mono_loader_lock ();
1521 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1523 mono_custom_attrs_free (tmp);
1524 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1525 mono_loader_unlock ();
1531 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1533 MONO_REQ_GC_NEUTRAL_MODE;
1535 if (ainfo && !ainfo->cached)
1540 * idx is the table index of the object
1541 * type is one of MONO_CUSTOM_ATTR_*
1544 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1546 MONO_REQ_GC_UNSAFE_MODE;
1548 MonoDynamicTable *table;
1549 MonoReflectionCustomAttr *cattr;
1551 guint32 count, i, token;
1553 char *p = blob_size;
1555 mono_error_init (error);
1557 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1560 count = mono_array_length (cattrs);
1561 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1562 table->rows += count;
1563 alloc_table (table, table->rows);
1564 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1565 idx <<= MONO_CUSTOM_ATTR_BITS;
1567 for (i = 0; i < count; ++i) {
1568 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1569 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1570 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1571 if (!mono_error_ok (error)) goto fail;
1572 type = mono_metadata_token_index (token);
1573 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1574 switch (mono_metadata_token_table (token)) {
1575 case MONO_TABLE_METHOD:
1576 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1578 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1579 * method, not the one returned by mono_image_create_token ().
1581 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1583 case MONO_TABLE_MEMBERREF:
1584 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1587 g_warning ("got wrong token in custom attr");
1590 values [MONO_CUSTOM_ATTR_TYPE] = type;
1592 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1593 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1594 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1595 values += MONO_CUSTOM_ATTR_SIZE;
1606 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1608 MONO_REQ_GC_UNSAFE_MODE;
1610 MonoDynamicTable *table;
1612 guint32 count, i, idx;
1613 MonoReflectionPermissionSet *perm;
1618 count = mono_array_length (permissions);
1619 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1620 table->rows += count;
1621 alloc_table (table, table->rows);
1623 for (i = 0; i < mono_array_length (permissions); ++i) {
1624 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1626 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1628 idx = mono_metadata_token_index (parent_token);
1629 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1630 switch (mono_metadata_token_table (parent_token)) {
1631 case MONO_TABLE_TYPEDEF:
1632 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1634 case MONO_TABLE_METHOD:
1635 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1637 case MONO_TABLE_ASSEMBLY:
1638 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1641 g_assert_not_reached ();
1644 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1645 values [MONO_DECL_SECURITY_PARENT] = idx;
1646 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1653 * Fill in the MethodDef and ParamDef tables for a method.
1654 * This is used for both normal methods and constructors.
1657 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1659 MONO_REQ_GC_UNSAFE_MODE;
1661 MonoDynamicTable *table;
1665 mono_error_init (error);
1667 /* room in this table is already allocated */
1668 table = &assembly->tables [MONO_TABLE_METHOD];
1669 *mb->table_idx = table->next_idx ++;
1670 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1671 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1672 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1673 values [MONO_METHOD_FLAGS] = mb->attrs;
1674 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1675 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1676 return_val_if_nok (error, FALSE);
1677 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1678 return_val_if_nok (error, FALSE);
1680 table = &assembly->tables [MONO_TABLE_PARAM];
1681 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1683 mono_image_add_decl_security (assembly,
1684 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1687 MonoDynamicTable *mtable;
1690 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1691 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1694 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1695 if (mono_array_get (mb->pinfo, gpointer, i))
1698 table->rows += count;
1699 alloc_table (table, table->rows);
1700 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1701 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1702 MonoReflectionParamBuilder *pb;
1703 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1704 values [MONO_PARAM_FLAGS] = pb->attrs;
1705 values [MONO_PARAM_SEQUENCE] = i;
1706 if (pb->name != NULL) {
1707 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1709 values [MONO_PARAM_NAME] = 0;
1711 values += MONO_PARAM_SIZE;
1712 if (pb->marshal_info) {
1714 alloc_table (mtable, mtable->rows);
1715 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1716 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1717 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1718 return_val_if_nok (error, FALSE);
1720 pb->table_idx = table->next_idx++;
1721 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1722 guint32 field_type = 0;
1723 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1725 alloc_table (mtable, mtable->rows);
1726 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1727 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1728 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1729 mvalues [MONO_CONSTANT_TYPE] = field_type;
1730 mvalues [MONO_CONSTANT_PADDING] = 0;
1739 #ifndef DISABLE_REFLECTION_EMIT
1741 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1743 MONO_REQ_GC_UNSAFE_MODE;
1745 mono_error_init (error);
1746 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1748 rmb->ilgen = mb->ilgen;
1749 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1750 return_val_if_nok (error, FALSE);
1751 rmb->parameters = mb->parameters;
1752 rmb->generic_params = mb->generic_params;
1753 rmb->generic_container = mb->generic_container;
1754 rmb->opt_types = NULL;
1755 rmb->pinfo = mb->pinfo;
1756 rmb->attrs = mb->attrs;
1757 rmb->iattrs = mb->iattrs;
1758 rmb->call_conv = mb->call_conv;
1759 rmb->code = mb->code;
1760 rmb->type = mb->type;
1761 rmb->name = mb->name;
1762 rmb->table_idx = &mb->table_idx;
1763 rmb->init_locals = mb->init_locals;
1764 rmb->skip_visibility = FALSE;
1765 rmb->return_modreq = mb->return_modreq;
1766 rmb->return_modopt = mb->return_modopt;
1767 rmb->param_modreq = mb->param_modreq;
1768 rmb->param_modopt = mb->param_modopt;
1769 rmb->permissions = mb->permissions;
1770 rmb->mhandle = mb->mhandle;
1775 rmb->charset = mb->charset;
1776 rmb->extra_flags = mb->extra_flags;
1777 rmb->native_cc = mb->native_cc;
1778 rmb->dllentry = mb->dllentry;
1786 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1788 MONO_REQ_GC_UNSAFE_MODE;
1790 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1792 mono_error_init (error);
1794 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1796 rmb->ilgen = mb->ilgen;
1797 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1798 return_val_if_nok (error, FALSE);
1799 rmb->parameters = mb->parameters;
1800 rmb->generic_params = NULL;
1801 rmb->generic_container = NULL;
1802 rmb->opt_types = NULL;
1803 rmb->pinfo = mb->pinfo;
1804 rmb->attrs = mb->attrs;
1805 rmb->iattrs = mb->iattrs;
1806 rmb->call_conv = mb->call_conv;
1808 rmb->type = mb->type;
1809 rmb->name = mono_string_new (mono_domain_get (), name);
1810 rmb->table_idx = &mb->table_idx;
1811 rmb->init_locals = mb->init_locals;
1812 rmb->skip_visibility = FALSE;
1813 rmb->return_modreq = NULL;
1814 rmb->return_modopt = NULL;
1815 rmb->param_modreq = mb->param_modreq;
1816 rmb->param_modopt = mb->param_modopt;
1817 rmb->permissions = mb->permissions;
1818 rmb->mhandle = mb->mhandle;
1826 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1828 MONO_REQ_GC_UNSAFE_MODE;
1830 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1832 rmb->ilgen = mb->ilgen;
1833 rmb->rtype = mb->rtype;
1834 rmb->parameters = mb->parameters;
1835 rmb->generic_params = NULL;
1836 rmb->generic_container = NULL;
1837 rmb->opt_types = NULL;
1839 rmb->attrs = mb->attrs;
1841 rmb->call_conv = mb->call_conv;
1843 rmb->type = (MonoObject *) mb->owner;
1844 rmb->name = mb->name;
1845 rmb->table_idx = NULL;
1846 rmb->init_locals = mb->init_locals;
1847 rmb->skip_visibility = mb->skip_visibility;
1848 rmb->return_modreq = NULL;
1849 rmb->return_modopt = NULL;
1850 rmb->param_modreq = NULL;
1851 rmb->param_modopt = NULL;
1852 rmb->permissions = NULL;
1853 rmb->mhandle = mb->mhandle;
1860 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1862 MONO_REQ_GC_UNSAFE_MODE;
1864 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1865 MonoDynamicTable *table;
1868 MonoReflectionMethod *m;
1871 mono_error_init (error);
1873 if (!mb->override_methods)
1876 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1877 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1879 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1881 alloc_table (table, table->rows);
1882 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1883 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1884 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1886 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1887 return_val_if_nok (error, FALSE);
1889 switch (mono_metadata_token_table (tok)) {
1890 case MONO_TABLE_MEMBERREF:
1891 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1893 case MONO_TABLE_METHOD:
1894 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1897 g_assert_not_reached ();
1899 values [MONO_METHODIMPL_DECLARATION] = tok;
1905 #ifndef DISABLE_REFLECTION_EMIT
1907 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1909 MONO_REQ_GC_UNSAFE_MODE;
1911 MonoDynamicTable *table;
1913 ReflectionMethodBuilder rmb;
1916 mono_error_init (error);
1918 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1919 !mono_image_basic_method (&rmb, assembly, error))
1922 mb->table_idx = *rmb.table_idx;
1924 if (mb->dll) { /* It's a P/Invoke method */
1926 /* map CharSet values to on-disk values */
1927 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1928 int extra_flags = mb->extra_flags;
1929 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1931 alloc_table (table, table->rows);
1932 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1934 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1935 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1937 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1939 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1940 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1941 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1942 table = &assembly->tables [MONO_TABLE_MODULEREF];
1944 alloc_table (table, table->rows);
1945 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1946 values [MONO_IMPLMAP_SCOPE] = table->rows;
1950 if (mb->generic_params) {
1951 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1952 table->rows += mono_array_length (mb->generic_params);
1953 alloc_table (table, table->rows);
1954 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1955 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1957 mono_image_get_generic_param_info (
1958 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1966 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1968 MONO_REQ_GC_UNSAFE_MODE;
1970 ReflectionMethodBuilder rmb;
1972 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1975 if (!mono_image_basic_method (&rmb, assembly, error))
1978 mb->table_idx = *rmb.table_idx;
1985 type_get_fully_qualified_name (MonoType *type)
1987 MONO_REQ_GC_NEUTRAL_MODE;
1989 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1993 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1995 MONO_REQ_GC_UNSAFE_MODE;
2000 klass = mono_class_from_mono_type (type);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2003 ta = klass->image->assembly;
2004 if (assembly_is_dynamic (ta) || (ta == ass)) {
2005 if (klass->generic_class || klass->generic_container)
2006 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2007 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2009 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2012 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2015 #ifndef DISABLE_REFLECTION_EMIT
2016 /*field_image is the image to which the eventual custom mods have been encoded against*/
2018 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2020 MONO_REQ_GC_NEUTRAL_MODE;
2023 guint32 idx, i, token;
2025 if (!assembly->save)
2028 sigbuffer_init (&buf, 32);
2030 sigbuffer_add_value (&buf, 0x06);
2031 /* encode custom attributes before the type */
2032 if (type->num_mods) {
2033 for (i = 0; i < type->num_mods; ++i) {
2036 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2037 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2039 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2041 token = type->modifiers [i].token;
2044 if (type->modifiers [i].required)
2045 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2047 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2049 sigbuffer_add_value (&buf, token);
2052 encode_type (assembly, type, &buf);
2053 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2054 sigbuffer_free (&buf);
2060 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2062 MONO_REQ_GC_UNSAFE_MODE;
2064 mono_error_init (error);
2068 guint32 typespec = 0;
2072 init_type_builder_generics (fb->type, error);
2073 return_val_if_nok (error, 0);
2075 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2076 return_val_if_nok (error, 0);
2077 klass = mono_class_from_mono_type (type);
2079 sigbuffer_init (&buf, 32);
2081 sigbuffer_add_value (&buf, 0x06);
2082 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2085 /* encode custom attributes before the type */
2087 if (klass->generic_container)
2088 typespec = create_typespec (assembly, type);
2091 MonoGenericClass *gclass;
2092 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2093 encode_generic_class (assembly, gclass, &buf);
2095 encode_type (assembly, type, &buf);
2097 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2098 sigbuffer_free (&buf);
2101 sigbuffer_free (&buf);
2106 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2108 MONO_REQ_GC_UNSAFE_MODE;
2110 char blob_size [64];
2111 char *b = blob_size;
2114 guint32 idx = 0, len = 0, dummy = 0;
2116 buf = (char *)g_malloc (64);
2118 *ret_type = MONO_TYPE_CLASS;
2120 box_val = (char*)&dummy;
2122 box_val = ((char*)val) + sizeof (MonoObject);
2123 *ret_type = val->vtable->klass->byval_arg.type;
2126 switch (*ret_type) {
2127 case MONO_TYPE_BOOLEAN:
2132 case MONO_TYPE_CHAR:
2149 case MONO_TYPE_VALUETYPE: {
2150 MonoClass *klass = val->vtable->klass;
2152 if (klass->enumtype) {
2153 *ret_type = mono_class_enum_basetype (klass)->type;
2155 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2158 g_error ("we can't encode valuetypes, we should have never reached this line");
2161 case MONO_TYPE_CLASS:
2163 case MONO_TYPE_STRING: {
2164 MonoString *str = (MonoString*)val;
2165 /* there is no signature */
2166 len = str->length * 2;
2167 mono_metadata_encode_value (len, b, &b);
2168 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2170 char *swapped = g_malloc (2 * mono_string_length (str));
2171 const char *p = (const char*)mono_string_chars (str);
2173 swap_with_size (swapped, p, 2, mono_string_length (str));
2174 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2178 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2184 case MONO_TYPE_GENERICINST:
2185 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2188 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2191 /* there is no signature */
2192 mono_metadata_encode_value (len, b, &b);
2193 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2194 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2195 swap_with_size (blob_size, box_val, len, 1);
2196 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2198 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2206 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2208 MONO_REQ_GC_UNSAFE_MODE;
2210 mono_error_init (error);
2216 sigbuffer_init (&buf, 32);
2218 sigbuffer_add_value (&buf, minfo->type);
2220 switch (minfo->type) {
2221 case MONO_NATIVE_BYVALTSTR:
2222 case MONO_NATIVE_BYVALARRAY:
2223 sigbuffer_add_value (&buf, minfo->count);
2225 case MONO_NATIVE_LPARRAY:
2226 if (minfo->eltype || minfo->has_size) {
2227 sigbuffer_add_value (&buf, minfo->eltype);
2228 if (minfo->has_size) {
2229 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2230 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2232 /* LAMESPEC: ElemMult is undocumented */
2233 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2237 case MONO_NATIVE_SAFEARRAY:
2239 sigbuffer_add_value (&buf, minfo->eltype);
2241 case MONO_NATIVE_CUSTOM:
2243 str = mono_string_to_utf8_checked (minfo->guid, error);
2244 if (!is_ok (error)) {
2245 sigbuffer_free (&buf);
2249 sigbuffer_add_value (&buf, len);
2250 sigbuffer_add_mem (&buf, str, len);
2253 sigbuffer_add_value (&buf, 0);
2255 /* native type name */
2256 sigbuffer_add_value (&buf, 0);
2257 /* custom marshaler type name */
2258 if (minfo->marshaltype || minfo->marshaltyperef) {
2259 if (minfo->marshaltyperef) {
2260 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2261 if (!is_ok (error)) {
2262 sigbuffer_free (&buf);
2265 str = type_get_fully_qualified_name (marshaltype);
2267 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2268 if (!is_ok (error)) {
2269 sigbuffer_free (&buf);
2274 sigbuffer_add_value (&buf, len);
2275 sigbuffer_add_mem (&buf, str, len);
2278 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2279 sigbuffer_add_value (&buf, 0);
2281 if (minfo->mcookie) {
2282 str = mono_string_to_utf8_checked (minfo->mcookie, error);
2283 if (!is_ok (error)) {
2284 sigbuffer_free (&buf);
2288 sigbuffer_add_value (&buf, len);
2289 sigbuffer_add_mem (&buf, str, len);
2292 sigbuffer_add_value (&buf, 0);
2298 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2299 sigbuffer_free (&buf);
2304 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2306 MONO_REQ_GC_UNSAFE_MODE;
2308 mono_error_init (error);
2310 MonoDynamicTable *table;
2313 /* maybe this fixup should be done in the C# code */
2314 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2315 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2316 table = &assembly->tables [MONO_TABLE_FIELD];
2317 fb->table_idx = table->next_idx ++;
2318 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2319 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2320 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2321 values [MONO_FIELD_FLAGS] = fb->attrs;
2322 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2323 return_if_nok (error);
2326 if (fb->offset != -1) {
2327 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2329 alloc_table (table, table->rows);
2330 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2331 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2332 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2334 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2335 MonoTypeEnum field_type = (MonoTypeEnum)0;
2336 table = &assembly->tables [MONO_TABLE_CONSTANT];
2338 alloc_table (table, table->rows);
2339 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2340 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2341 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2342 values [MONO_CONSTANT_TYPE] = field_type;
2343 values [MONO_CONSTANT_PADDING] = 0;
2345 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2347 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2349 alloc_table (table, table->rows);
2350 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2351 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2353 * We store it in the code section because it's simpler for now.
2356 if (mono_array_length (fb->rva_data) >= 10)
2357 stream_data_align (&assembly->code);
2358 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2360 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2361 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2363 if (fb->marshal_info) {
2364 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2366 alloc_table (table, table->rows);
2367 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2368 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2369 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2370 return_if_nok (error);
2375 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2377 MONO_REQ_GC_UNSAFE_MODE;
2379 mono_error_init (error);
2382 guint32 nparams = 0;
2383 MonoReflectionMethodBuilder *mb = fb->get_method;
2384 MonoReflectionMethodBuilder *smb = fb->set_method;
2387 if (mb && mb->parameters)
2388 nparams = mono_array_length (mb->parameters);
2389 if (!mb && smb && smb->parameters)
2390 nparams = mono_array_length (smb->parameters) - 1;
2391 sigbuffer_init (&buf, 32);
2392 if (fb->call_conv & 0x20)
2393 sigbuffer_add_byte (&buf, 0x28);
2395 sigbuffer_add_byte (&buf, 0x08);
2396 sigbuffer_add_value (&buf, nparams);
2398 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2401 for (i = 0; i < nparams; ++i) {
2402 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2403 encode_reflection_type (assembly, pt, &buf, error);
2407 } else if (smb && smb->parameters) {
2408 /* the property type is the last param */
2409 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2413 for (i = 0; i < nparams; ++i) {
2414 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2415 encode_reflection_type (assembly, pt, &buf, error);
2420 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2425 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2426 sigbuffer_free (&buf);
2429 sigbuffer_free (&buf);
2434 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2436 MONO_REQ_GC_UNSAFE_MODE;
2438 mono_error_init (error);
2440 MonoDynamicTable *table;
2442 guint num_methods = 0;
2446 * we need to set things in the following tables:
2447 * PROPERTYMAP (info already filled in _get_type_info ())
2448 * PROPERTY (rows already preallocated in _get_type_info ())
2449 * METHOD (method info already done with the generic method code)
2453 table = &assembly->tables [MONO_TABLE_PROPERTY];
2454 pb->table_idx = table->next_idx ++;
2455 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2456 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2457 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2458 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2459 return_if_nok (error);
2462 /* FIXME: we still don't handle 'other' methods */
2463 if (pb->get_method) num_methods ++;
2464 if (pb->set_method) num_methods ++;
2466 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2467 table->rows += num_methods;
2468 alloc_table (table, table->rows);
2470 if (pb->get_method) {
2471 semaidx = table->next_idx ++;
2472 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2473 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2474 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2475 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2477 if (pb->set_method) {
2478 semaidx = table->next_idx ++;
2479 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2480 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2481 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2482 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2484 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2485 MonoTypeEnum field_type = (MonoTypeEnum)0;
2486 table = &assembly->tables [MONO_TABLE_CONSTANT];
2488 alloc_table (table, table->rows);
2489 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2490 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2491 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2492 values [MONO_CONSTANT_TYPE] = field_type;
2493 values [MONO_CONSTANT_PADDING] = 0;
2498 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2500 MONO_REQ_GC_UNSAFE_MODE;
2502 MonoDynamicTable *table;
2504 guint num_methods = 0;
2508 * we need to set things in the following tables:
2509 * EVENTMAP (info already filled in _get_type_info ())
2510 * EVENT (rows already preallocated in _get_type_info ())
2511 * METHOD (method info already done with the generic method code)
2514 table = &assembly->tables [MONO_TABLE_EVENT];
2515 eb->table_idx = table->next_idx ++;
2516 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2517 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2518 values [MONO_EVENT_FLAGS] = eb->attrs;
2519 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2520 return_if_nok (error);
2521 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2524 * FIXME: we still don't handle 'other' methods
2526 if (eb->add_method) num_methods ++;
2527 if (eb->remove_method) num_methods ++;
2528 if (eb->raise_method) num_methods ++;
2530 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2531 table->rows += num_methods;
2532 alloc_table (table, table->rows);
2534 if (eb->add_method) {
2535 semaidx = table->next_idx ++;
2536 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2537 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2538 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2539 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2541 if (eb->remove_method) {
2542 semaidx = table->next_idx ++;
2543 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2544 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2545 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2546 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2548 if (eb->raise_method) {
2549 semaidx = table->next_idx ++;
2550 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2551 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2552 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2553 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2558 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2560 MONO_REQ_GC_UNSAFE_MODE;
2562 mono_error_init (error);
2564 MonoDynamicTable *table;
2565 guint32 num_constraints, i;
2569 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2570 num_constraints = gparam->iface_constraints ?
2571 mono_array_length (gparam->iface_constraints) : 0;
2572 table->rows += num_constraints;
2573 if (gparam->base_type)
2575 alloc_table (table, table->rows);
2577 if (gparam->base_type) {
2578 table_idx = table->next_idx ++;
2579 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2581 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2582 return_if_nok (error);
2583 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2584 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2587 for (i = 0; i < num_constraints; i++) {
2588 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2589 gparam->iface_constraints, gpointer, i);
2591 table_idx = table->next_idx ++;
2592 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2594 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2595 return_if_nok (error);
2597 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2598 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2603 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2605 MONO_REQ_GC_UNSAFE_MODE;
2607 GenericParamTableEntry *entry;
2610 * The GenericParam table must be sorted according to the `owner' field.
2611 * We need to do this sorting prior to writing the GenericParamConstraint
2612 * table, since we have to use the final GenericParam table indices there
2613 * and they must also be sorted.
2616 entry = g_new0 (GenericParamTableEntry, 1);
2617 entry->owner = owner;
2618 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2619 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2620 entry->gparam = gparam;
2622 g_ptr_array_add (assembly->gen_params, entry);
2626 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2628 MONO_REQ_GC_UNSAFE_MODE;
2630 MonoDynamicTable *table;
2631 MonoGenericParam *param;
2635 mono_error_init (error);
2637 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2638 table_idx = table->next_idx ++;
2639 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2641 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2642 return_val_if_nok (error, FALSE);
2644 param = gparam_type->data.generic_param;
2646 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2647 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2648 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2649 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2651 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2654 encode_constraints (entry->gparam, table_idx, assembly, error);
2655 return_val_if_nok (error, FALSE);
2661 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2663 MONO_REQ_GC_UNSAFE_MODE;
2665 MonoDynamicTable *table;
2668 guint32 cols [MONO_ASSEMBLY_SIZE];
2672 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2675 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2676 table = &assembly->tables [MONO_TABLE_MODULEREF];
2677 token = table->next_idx ++;
2679 alloc_table (table, table->rows);
2680 values = table->values + token * MONO_MODULEREF_SIZE;
2681 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2683 token <<= MONO_RESOLUTION_SCOPE_BITS;
2684 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2685 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2690 if (assembly_is_dynamic (image->assembly))
2692 memset (cols, 0, sizeof (cols));
2694 /* image->assembly->image is the manifest module */
2695 image = image->assembly->image;
2696 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2699 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2700 token = table->next_idx ++;
2702 alloc_table (table, table->rows);
2703 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2704 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2705 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2706 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2707 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2708 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2709 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2710 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2711 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2713 if (strcmp ("", image->assembly->aname.culture)) {
2714 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2715 image->assembly->aname.culture);
2718 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2719 guchar pubtoken [9];
2721 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2722 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2724 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2726 token <<= MONO_RESOLUTION_SCOPE_BITS;
2727 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2728 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2733 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2735 MONO_REQ_GC_NEUTRAL_MODE;
2737 MonoDynamicTable *table;
2742 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2745 sigbuffer_init (&buf, 32);
2746 switch (type->type) {
2747 case MONO_TYPE_FNPTR:
2749 case MONO_TYPE_SZARRAY:
2750 case MONO_TYPE_ARRAY:
2752 case MONO_TYPE_MVAR:
2753 case MONO_TYPE_GENERICINST:
2754 encode_type (assembly, type, &buf);
2756 case MONO_TYPE_CLASS:
2757 case MONO_TYPE_VALUETYPE: {
2758 MonoClass *k = mono_class_from_mono_type (type);
2759 if (!k || !k->generic_container) {
2760 sigbuffer_free (&buf);
2763 encode_type (assembly, type, &buf);
2767 sigbuffer_free (&buf);
2771 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2772 if (assembly->save) {
2773 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2774 alloc_table (table, table->rows + 1);
2775 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2776 values [MONO_TYPESPEC_SIGNATURE] = token;
2778 sigbuffer_free (&buf);
2780 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2781 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2787 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2789 MONO_REQ_GC_UNSAFE_MODE;
2791 MonoDynamicTable *table;
2793 guint32 token, scope, enclosing;
2796 /* if the type requires a typespec, we must try that first*/
2797 if (try_typespec && (token = create_typespec (assembly, type)))
2799 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2802 klass = mono_class_from_mono_type (type);
2804 klass = mono_class_from_mono_type (type);
2807 * If it's in the same module and not a generic type parameter:
2809 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2810 (type->type != MONO_TYPE_MVAR)) {
2811 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2812 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2813 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2817 if (klass->nested_in) {
2818 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2819 /* get the typeref idx of the enclosing type */
2820 enclosing >>= MONO_TYPEDEFORREF_BITS;
2821 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2823 scope = resolution_scope_from_image (assembly, klass->image);
2825 table = &assembly->tables [MONO_TABLE_TYPEREF];
2826 if (assembly->save) {
2827 alloc_table (table, table->rows + 1);
2828 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2829 values [MONO_TYPEREF_SCOPE] = scope;
2830 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2831 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2833 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2834 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2836 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2841 * Despite the name, we handle also TypeSpec (with the above helper).
2844 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2846 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2849 #ifndef DISABLE_REFLECTION_EMIT
2851 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2853 MONO_REQ_GC_NEUTRAL_MODE;
2855 MonoDynamicTable *table;
2857 guint32 token, pclass;
2859 switch (parent & MONO_TYPEDEFORREF_MASK) {
2860 case MONO_TYPEDEFORREF_TYPEREF:
2861 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2863 case MONO_TYPEDEFORREF_TYPESPEC:
2864 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2866 case MONO_TYPEDEFORREF_TYPEDEF:
2867 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2870 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2873 /* extract the index */
2874 parent >>= MONO_TYPEDEFORREF_BITS;
2876 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2878 if (assembly->save) {
2879 alloc_table (table, table->rows + 1);
2880 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2881 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2882 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2883 values [MONO_MEMBERREF_SIGNATURE] = sig;
2886 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2893 * Insert a memberef row into the metadata: the token that point to the memberref
2894 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2895 * mono_image_get_fieldref_token()).
2896 * The sig param is an index to an already built signature.
2899 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2901 MONO_REQ_GC_NEUTRAL_MODE;
2903 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2904 return mono_image_add_memberef_row (assembly, parent, name, sig);
2909 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2911 MONO_REQ_GC_NEUTRAL_MODE;
2914 MonoMethodSignature *sig;
2916 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2918 if (create_typespec) {
2919 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2924 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2925 if (token && !create_typespec)
2928 g_assert (!method->is_inflated);
2931 * A methodref signature can't contain an unmanaged calling convention.
2933 sig = mono_metadata_signature_dup (mono_method_signature (method));
2934 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2935 sig->call_convention = MONO_CALL_DEFAULT;
2936 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2937 method->name, method_encode_signature (assembly, sig));
2939 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2942 if (create_typespec) {
2943 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2944 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2945 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2947 if (assembly->save) {
2950 alloc_table (table, table->rows + 1);
2951 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2952 values [MONO_METHODSPEC_METHOD] = token;
2953 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2956 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2958 /*methodspec and memberef tokens are diferent, */
2959 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2966 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2968 guint32 token, parent, sig;
2969 ReflectionMethodBuilder rmb;
2970 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2972 mono_error_init (error);
2973 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2977 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2981 * A methodref signature can't contain an unmanaged calling convention.
2982 * Since some flags are encoded as part of call_conv, we need to check against it.
2984 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2985 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2987 sig = method_builder_encode_signature (assembly, &rmb, error);
2988 return_val_if_nok (error, 0);
2990 if (tb->generic_params) {
2991 parent = create_generic_typespec (assembly, tb, error);
2992 return_val_if_nok (error, 0);
2994 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2995 return_val_if_nok (error, 0);
2997 parent = mono_image_typedef_or_ref (assembly, t);
3000 char *name = mono_string_to_utf8_checked (method->name, error);
3001 return_val_if_nok (error, 0);
3003 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3006 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3012 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3013 const gchar *name, guint32 sig)
3015 MonoDynamicTable *table;
3019 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3021 if (assembly->save) {
3022 alloc_table (table, table->rows + 1);
3023 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3024 values [MONO_MEMBERREF_CLASS] = original;
3025 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3026 values [MONO_MEMBERREF_SIGNATURE] = sig;
3029 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3036 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3040 guint32 nparams = mono_array_length (mb->generic_params);
3043 if (!assembly->save)
3046 sigbuffer_init (&buf, 32);
3048 sigbuffer_add_value (&buf, 0xa);
3049 sigbuffer_add_value (&buf, nparams);
3051 for (i = 0; i < nparams; i++) {
3052 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3053 sigbuffer_add_value (&buf, i);
3056 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3057 sigbuffer_free (&buf);
3062 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3064 MonoDynamicTable *table;
3066 guint32 token, mtoken = 0;
3068 mono_error_init (error);
3069 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3073 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3075 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3076 if (!mono_error_ok (error))
3079 switch (mono_metadata_token_table (mtoken)) {
3080 case MONO_TABLE_MEMBERREF:
3081 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3083 case MONO_TABLE_METHOD:
3084 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3087 g_assert_not_reached ();
3090 if (assembly->save) {
3091 alloc_table (table, table->rows + 1);
3092 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3093 values [MONO_METHODSPEC_METHOD] = mtoken;
3094 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3097 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3100 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3105 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3109 mono_error_init (error);
3111 if (mb->generic_params && create_methodspec)
3112 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3114 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3118 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3119 if (!mono_error_ok (error))
3121 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3126 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3128 guint32 token, parent, sig;
3129 ReflectionMethodBuilder rmb;
3131 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3133 mono_error_init (error);
3135 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3139 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3142 if (tb->generic_params) {
3143 parent = create_generic_typespec (assembly, tb, error);
3144 return_val_if_nok (error, 0);
3146 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3147 return_val_if_nok (error, 0);
3148 parent = mono_image_typedef_or_ref (assembly, type);
3151 name = mono_string_to_utf8_checked (rmb.name, error);
3152 return_val_if_nok (error, 0);
3153 sig = method_builder_encode_signature (assembly, &rmb, error);
3154 return_val_if_nok (error, 0);
3156 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3159 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3165 is_field_on_inst (MonoClassField *field)
3167 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3171 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3174 get_field_on_inst_generic_type (MonoClassField *field)
3176 MonoClass *klass, *gtd;
3177 MonoDynamicGenericClass *dgclass;
3180 g_assert (is_field_on_inst (field));
3182 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3184 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3185 field_index = field - dgclass->fields;
3186 return dgclass->field_generic_types [field_index];
3189 klass = field->parent;
3190 gtd = klass->generic_class->container_class;
3192 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3193 field_index = field - klass->fields;
3194 return gtd->fields [field_index].type;
3197 g_assert_not_reached ();
3201 #ifndef DISABLE_REFLECTION_EMIT
3203 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3209 g_assert (field->parent);
3211 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3216 int index = field - field->parent->fields;
3217 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3219 if (is_field_on_inst (field))
3220 type = get_field_on_inst_generic_type (field);
3222 type = mono_field_get_type (field);
3224 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3225 mono_field_get_name (field),
3226 fieldref_encode_signature (assembly, field->parent->image, type));
3227 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3232 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3236 MonoGenericClass *gclass;
3240 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3243 if (is_sre_field_builder (mono_object_class (f->fb))) {
3244 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3245 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3246 return_val_if_nok (error, 0);
3247 klass = mono_class_from_mono_type (type);
3248 gclass = type->data.generic_class;
3249 g_assert (gclass->is_dynamic);
3251 guint32 sig_token = field_encode_signature (assembly, fb, error);
3252 return_val_if_nok (error, 0);
3253 name = mono_string_to_utf8_checked (fb->name, error);
3254 return_val_if_nok (error, 0);
3255 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3257 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3259 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3261 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3262 return_val_if_nok (error, 0);
3263 klass = mono_class_from_mono_type (type);
3265 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3266 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3268 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3269 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3272 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3277 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3281 MonoGenericClass *gclass;
3284 mono_error_init (error);
3286 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3288 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3292 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3293 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3294 ReflectionMethodBuilder rmb;
3297 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3298 return_val_if_nok (error, 0);
3299 klass = mono_class_from_mono_type (type);
3301 gclass = type->data.generic_class;
3302 g_assert (gclass->is_dynamic);
3304 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3307 sig = method_builder_encode_signature (assembly, &rmb, error);
3308 return_val_if_nok (error, 0);
3310 name = mono_string_to_utf8_checked (rmb.name, error);
3311 return_val_if_nok (error, 0);
3313 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3315 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3316 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3318 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3319 return_val_if_nok (error, 0);
3320 klass = mono_class_from_mono_type (type);
3322 sig = method_encode_signature (assembly, mono_method_signature (mm));
3323 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3325 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3326 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3330 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3335 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3338 MonoGenericContext tmp_context;
3339 MonoType **type_argv;
3340 MonoGenericInst *ginst;
3341 MonoMethod *method, *inflated;
3344 mono_error_init (error);
3346 init_type_builder_generics ((MonoObject*)m->inst, error);
3347 return_val_if_nok (error, NULL);
3349 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3350 return_val_if_nok (error, NULL);
3352 klass = method->klass;
3354 if (m->method_args == NULL)
3357 if (method->is_inflated)
3358 method = ((MonoMethodInflated *) method)->declaring;
3360 count = mono_array_length (m->method_args);
3362 type_argv = g_new0 (MonoType *, count);
3363 for (i = 0; i < count; i++) {
3364 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3365 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3366 return_val_if_nok (error, NULL);
3368 ginst = mono_metadata_get_generic_inst (count, type_argv);
3371 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3372 tmp_context.method_inst = ginst;
3374 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3375 mono_error_assert_ok (error);
3380 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3382 guint32 sig, token = 0;
3386 mono_error_init (error);
3388 if (m->method_args) {
3389 MonoMethod *inflated;
3391 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3392 return_val_if_nok (error, 0);
3394 if (create_methodspec)
3395 token = mono_image_get_methodspec_token (assembly, inflated);
3397 token = mono_image_get_inflated_method_token (assembly, inflated);
3401 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3405 if (is_sre_method_builder (mono_object_class (m->mb))) {
3406 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3407 MonoGenericClass *gclass;
3408 ReflectionMethodBuilder rmb;
3411 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3412 return_val_if_nok (error, 0);
3413 klass = mono_class_from_mono_type (type);
3414 gclass = type->data.generic_class;
3415 g_assert (gclass->is_dynamic);
3417 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3420 sig = method_builder_encode_signature (assembly, &rmb, error);
3421 return_val_if_nok (error, 0);
3423 name = mono_string_to_utf8_checked (rmb.name, error);
3424 return_val_if_nok (error, 0);
3426 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3428 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3429 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3431 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3432 return_val_if_nok (error, 0);
3433 klass = mono_class_from_mono_type (type);
3435 sig = method_encode_signature (assembly, mono_method_signature (mm));
3436 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3438 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3439 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3442 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3447 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3451 guint32 nparams = context->method_inst->type_argc;
3454 if (!assembly->save)
3457 sigbuffer_init (&buf, 32);
3459 * FIXME: vararg, explicit_this, differenc call_conv values...
3461 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3462 sigbuffer_add_value (&buf, nparams);
3464 for (i = 0; i < nparams; i++)
3465 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3467 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3468 sigbuffer_free (&buf);
3473 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3475 MonoDynamicTable *table;
3477 guint32 token, mtoken = 0, sig;
3478 MonoMethodInflated *imethod;
3479 MonoMethod *declaring;
3481 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3483 g_assert (method->is_inflated);
3484 imethod = (MonoMethodInflated *) method;
3485 declaring = imethod->declaring;
3487 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3488 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3490 if (!mono_method_signature (declaring)->generic_param_count)
3493 switch (mono_metadata_token_table (mtoken)) {
3494 case MONO_TABLE_MEMBERREF:
3495 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3497 case MONO_TABLE_METHOD:
3498 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3501 g_assert_not_reached ();
3504 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3506 if (assembly->save) {
3507 alloc_table (table, table->rows + 1);
3508 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3509 values [MONO_METHODSPEC_METHOD] = mtoken;
3510 values [MONO_METHODSPEC_SIGNATURE] = sig;
3513 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3520 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3522 MonoMethodInflated *imethod;
3525 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3529 g_assert (method->is_inflated);
3530 imethod = (MonoMethodInflated *) method;
3532 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3533 token = method_encode_methodspec (assembly, method);
3535 guint32 sig = method_encode_signature (
3536 assembly, mono_method_signature (imethod->declaring));
3537 token = mono_image_get_memberref_token (
3538 assembly, &method->klass->byval_arg, method->name, sig);
3541 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3546 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3548 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3551 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3552 token = mono_image_get_memberref_token (
3553 assembly, &m->klass->byval_arg, m->name, sig);
3559 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3561 MonoDynamicTable *table;
3570 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3571 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3572 * Because of this, we must not insert it into the `typeref' hash table.
3574 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3575 return_val_if_nok (error, 0);
3576 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3580 sigbuffer_init (&buf, 32);
3582 g_assert (tb->generic_params);
3583 klass = mono_class_from_mono_type (type);
3585 if (tb->generic_container) {
3586 if (!mono_reflection_create_generic_class (tb, error))
3590 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3591 g_assert (klass->generic_container);
3592 sigbuffer_add_value (&buf, klass->byval_arg.type);
3593 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3595 count = mono_array_length (tb->generic_params);
3596 sigbuffer_add_value (&buf, count);
3597 for (i = 0; i < count; i++) {
3598 MonoReflectionGenericParam *gparam;
3600 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3601 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3605 encode_type (assembly, gparam_type, &buf);
3608 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3610 if (assembly->save) {
3611 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3612 alloc_table (table, table->rows + 1);
3613 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3614 values [MONO_TYPESPEC_SIGNATURE] = token;
3616 sigbuffer_free (&buf);
3618 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3619 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3623 sigbuffer_free (&buf);
3628 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3631 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3633 int i, count, len, pos;
3636 mono_error_init (error);
3640 count += mono_array_length (modreq);
3642 count += mono_array_length (modopt);
3645 return mono_metadata_type_dup (NULL, type);
3647 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3648 t = (MonoType *)g_malloc (len);
3649 memcpy (t, type, MONO_SIZEOF_TYPE);
3651 t->num_mods = count;
3654 for (i = 0; i < mono_array_length (modreq); ++i) {
3655 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3658 t->modifiers [pos].required = 1;
3659 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3664 for (i = 0; i < mono_array_length (modopt); ++i) {
3665 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3668 t->modifiers [pos].required = 0;
3669 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3681 init_type_builder_generics (MonoObject *type, MonoError *error)
3683 MonoReflectionTypeBuilder *tb;
3685 mono_error_init (error);
3687 if (!is_sre_type_builder(mono_object_class (type)))
3689 tb = (MonoReflectionTypeBuilder *)type;
3691 if (tb && tb->generic_container)
3692 mono_reflection_create_generic_class (tb, error);
3696 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3698 MonoDynamicTable *table;
3699 MonoType *custom = NULL, *type;
3701 guint32 token, pclass, parent, sig;
3704 mono_error_init (error);
3706 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3710 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3711 return_val_if_nok (error, 0);
3712 /* FIXME: is this call necessary? */
3713 mono_class_from_mono_type (typeb);
3715 /*FIXME this is one more layer of ugliness due how types are created.*/
3716 init_type_builder_generics (fb->type, error);
3717 return_val_if_nok (error, 0);
3719 /* fb->type does not include the custom modifiers */
3720 /* FIXME: We should do this in one place when a fieldbuilder is created */
3721 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3722 return_val_if_nok (error, 0);
3724 if (fb->modreq || fb->modopt) {
3725 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3726 return_val_if_nok (error, 0);
3729 sig = fieldref_encode_signature (assembly, NULL, type);
3732 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3733 return_val_if_nok (error, 0);
3734 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3736 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3737 parent >>= MONO_TYPEDEFORREF_BITS;
3739 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3741 name = mono_string_to_utf8_checked (fb->name, error);
3742 return_val_if_nok (error, 0);
3744 if (assembly->save) {
3745 alloc_table (table, table->rows + 1);
3746 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3747 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3748 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3749 values [MONO_MEMBERREF_SIGNATURE] = sig;
3752 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3754 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3760 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3766 mono_error_init (error);
3768 if (!assembly->save)
3771 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3772 g_assert (helper->type == 2);
3774 if (helper->arguments)
3775 nargs = mono_array_length (helper->arguments);
3779 sigbuffer_init (&buf, 32);
3781 /* Encode calling convention */
3782 /* Change Any to Standard */
3783 if ((helper->call_conv & 0x03) == 0x03)
3784 helper->call_conv = 0x01;
3785 /* explicit_this implies has_this */
3786 if (helper->call_conv & 0x40)
3787 helper->call_conv &= 0x20;
3789 if (helper->call_conv == 0) { /* Unmanaged */
3790 idx = helper->unmanaged_call_conv - 1;
3793 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3794 if (helper->call_conv & 0x02) /* varargs */
3798 sigbuffer_add_byte (&buf, idx);
3799 sigbuffer_add_value (&buf, nargs);
3800 encode_reflection_type (assembly, helper->return_type, &buf, error);
3803 for (i = 0; i < nargs; ++i) {
3804 MonoArray *modreqs = NULL;
3805 MonoArray *modopts = NULL;
3806 MonoReflectionType *pt;
3808 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3809 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3810 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3811 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3813 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3816 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3817 encode_reflection_type (assembly, pt, &buf, error);
3821 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3822 sigbuffer_free (&buf);
3826 sigbuffer_free (&buf);
3831 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3834 MonoDynamicTable *table;
3837 mono_error_init (error);
3839 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3840 idx = table->next_idx ++;
3842 alloc_table (table, table->rows);
3843 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3845 values [MONO_STAND_ALONE_SIGNATURE] =
3846 mono_reflection_encode_sighelper (assembly, helper, error);
3847 return_val_if_nok (error, 0);
3853 reflection_cc_to_file (int call_conv) {
3854 switch (call_conv & 0x3) {
3856 case 1: return MONO_CALL_DEFAULT;
3857 case 2: return MONO_CALL_VARARG;
3859 g_assert_not_reached ();
3863 #endif /* !DISABLE_REFLECTION_EMIT */
3867 MonoMethodSignature *sig;
3872 #ifndef DISABLE_REFLECTION_EMIT
3874 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3879 MonoMethodSignature *sig;
3880 ArrayMethod *am = NULL;
3883 mono_error_init (error);
3885 nparams = mono_array_length (m->parameters);
3886 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3888 sig->sentinelpos = -1;
3889 sig->call_convention = reflection_cc_to_file (m->call_conv);
3890 sig->param_count = nparams;
3892 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3896 sig->ret = &mono_defaults.void_class->byval_arg;
3898 mtype = mono_reflection_type_get_handle (m->parent, error);
3902 for (i = 0; i < nparams; ++i) {
3903 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3908 name = mono_string_to_utf8_checked (m->name, error);
3911 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3912 am = (ArrayMethod *)tmp->data;
3913 if (strcmp (name, am->name) == 0 &&
3914 mono_metadata_type_equal (am->parent, mtype) &&
3915 mono_metadata_signature_equal (am->sig, sig)) {
3918 m->table_idx = am->token & 0xffffff;
3922 am = g_new0 (ArrayMethod, 1);
3926 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3927 method_encode_signature (assembly, sig));
3928 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3929 m->table_idx = am->token & 0xffffff;
3940 * Insert into the metadata tables all the info about the TypeBuilder tb.
3941 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3944 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3946 MonoDynamicTable *table;
3948 int i, is_object = 0, is_system = 0;
3951 mono_error_init (error);
3953 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3954 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3955 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3956 n = mono_string_to_utf8_checked (tb->name, error);
3957 return_val_if_nok (error, FALSE);
3958 if (strcmp (n, "Object") == 0)
3960 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3962 n = mono_string_to_utf8_checked (tb->nspace, error);
3963 return_val_if_nok (error, FALSE);
3964 if (strcmp (n, "System") == 0)
3966 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3968 if (tb->parent && !(is_system && is_object) &&
3969 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3970 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3971 return_val_if_nok (error, FALSE);
3972 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3974 values [MONO_TYPEDEF_EXTENDS] = 0;
3976 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3977 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3980 * if we have explicitlayout or sequentiallayouts, output data in the
3981 * ClassLayout table.
3983 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3984 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3985 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3987 alloc_table (table, table->rows);
3988 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3989 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3990 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3991 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3994 /* handle interfaces */
3995 if (tb->interfaces) {
3996 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3998 table->rows += mono_array_length (tb->interfaces);
3999 alloc_table (table, table->rows);
4000 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4001 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4002 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4003 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4004 return_val_if_nok (error, FALSE);
4005 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4006 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4007 values += MONO_INTERFACEIMPL_SIZE;
4013 table = &assembly->tables [MONO_TABLE_FIELD];
4014 table->rows += tb->num_fields;
4015 alloc_table (table, table->rows);
4016 for (i = 0; i < tb->num_fields; ++i) {
4017 mono_image_get_field_info (
4018 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4019 return_val_if_nok (error, FALSE);
4023 /* handle constructors */
4025 table = &assembly->tables [MONO_TABLE_METHOD];
4026 table->rows += mono_array_length (tb->ctors);
4027 alloc_table (table, table->rows);
4028 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4029 if (!mono_image_get_ctor_info (domain,
4030 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4036 /* handle methods */
4038 table = &assembly->tables [MONO_TABLE_METHOD];
4039 table->rows += tb->num_methods;
4040 alloc_table (table, table->rows);
4041 for (i = 0; i < tb->num_methods; ++i) {
4042 if (!mono_image_get_method_info (
4043 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4048 /* Do the same with properties etc.. */
4049 if (tb->events && mono_array_length (tb->events)) {
4050 table = &assembly->tables [MONO_TABLE_EVENT];
4051 table->rows += mono_array_length (tb->events);
4052 alloc_table (table, table->rows);
4053 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4055 alloc_table (table, table->rows);
4056 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4057 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4058 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4059 for (i = 0; i < mono_array_length (tb->events); ++i) {
4060 mono_image_get_event_info (
4061 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4062 return_val_if_nok (error, FALSE);
4065 if (tb->properties && mono_array_length (tb->properties)) {
4066 table = &assembly->tables [MONO_TABLE_PROPERTY];
4067 table->rows += mono_array_length (tb->properties);
4068 alloc_table (table, table->rows);
4069 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4071 alloc_table (table, table->rows);
4072 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4073 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4074 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4075 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4076 mono_image_get_property_info (
4077 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4078 return_val_if_nok (error, FALSE);
4082 /* handle generic parameters */
4083 if (tb->generic_params) {
4084 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4085 table->rows += mono_array_length (tb->generic_params);
4086 alloc_table (table, table->rows);
4087 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4088 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4090 mono_image_get_generic_param_info (
4091 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4095 mono_image_add_decl_security (assembly,
4096 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4099 MonoDynamicTable *ntable;
4101 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4102 ntable->rows += mono_array_length (tb->subtypes);
4103 alloc_table (ntable, ntable->rows);
4104 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4106 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4107 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4109 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4110 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4111 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4112 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4113 mono_string_to_utf8 (tb->name), tb->table_idx,
4114 ntable->next_idx, ntable->rows);*/
4115 values += MONO_NESTED_CLASS_SIZE;
4125 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4129 mono_ptr_array_append (*types, type);
4131 if (!type->subtypes)
4134 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4135 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4136 collect_types (types, subtype);
4141 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4143 if ((*type1)->table_idx < (*type2)->table_idx)
4146 if ((*type1)->table_idx > (*type2)->table_idx)
4153 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4156 mono_error_init (error);
4159 for (i = 0; i < mono_array_length (pinfo); ++i) {
4160 MonoReflectionParamBuilder *pb;
4161 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4164 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4172 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4175 mono_error_init (error);
4177 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4180 for (i = 0; i < tb->num_fields; ++i) {
4181 MonoReflectionFieldBuilder* fb;
4182 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4183 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4188 for (i = 0; i < mono_array_length (tb->events); ++i) {
4189 MonoReflectionEventBuilder* eb;
4190 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4191 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4195 if (tb->properties) {
4196 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4197 MonoReflectionPropertyBuilder* pb;
4198 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4199 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4204 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4205 MonoReflectionCtorBuilder* cb;
4206 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4207 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4208 !params_add_cattrs (assembly, cb->pinfo, error))
4214 for (i = 0; i < tb->num_methods; ++i) {
4215 MonoReflectionMethodBuilder* mb;
4216 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4217 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4218 !params_add_cattrs (assembly, mb->pinfo, error))
4224 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4225 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4234 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4238 mono_error_init (error);
4240 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4243 if (moduleb->global_methods) {
4244 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4245 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4246 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4247 !params_add_cattrs (assembly, mb->pinfo, error))
4252 if (moduleb->global_fields) {
4253 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4254 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4255 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4260 if (moduleb->types) {
4261 for (i = 0; i < moduleb->num_types; ++i) {
4262 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4271 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4274 MonoDynamicTable *table;
4278 char *b = blob_size;
4281 table = &assembly->tables [MONO_TABLE_FILE];
4283 alloc_table (table, table->rows);
4284 values = table->values + table->next_idx * MONO_FILE_SIZE;
4285 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4286 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4287 if (image_is_dynamic (module->image)) {
4288 /* This depends on the fact that the main module is emitted last */
4289 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, &error);
4290 mono_error_raise_exception (&error); /* FIXME don't raise here */
4291 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4294 path = g_strdup (module->image->name);
4296 mono_sha1_get_digest_from_file (path, hash);
4299 mono_metadata_encode_value (20, b, &b);
4300 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4301 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4306 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4308 MonoDynamicTable *table;
4311 table = &assembly->tables [MONO_TABLE_MODULE];
4312 mb->table_idx = table->next_idx ++;
4313 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4314 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4317 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4318 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4319 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4320 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4324 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4325 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4327 MonoDynamicTable *table;
4331 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4332 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4335 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4337 alloc_table (table, table->rows);
4338 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4340 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4341 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4342 if (klass->nested_in)
4343 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4345 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4346 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4347 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4349 res = table->next_idx;
4353 /* Emit nested types */
4354 if (klass->ext && klass->ext->nested_classes) {
4357 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4358 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4365 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4366 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4372 mono_error_init (error);
4374 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4375 return_if_nok (error);
4377 klass = mono_class_from_mono_type (t);
4379 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4381 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4382 parent_index, assembly);
4386 * We need to do this ourselves since klass->nested_classes is not set up.
4389 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4390 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4391 return_if_nok (error);
4397 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4398 guint32 module_index, MonoDynamicImage *assembly)
4400 MonoImage *image = module->image;
4404 t = &image->tables [MONO_TABLE_TYPEDEF];
4406 for (i = 0; i < t->rows; ++i) {
4408 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4409 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4411 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4412 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4417 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4419 MonoDynamicTable *table;
4421 guint32 scope, scope_idx, impl, current_idx;
4422 gboolean forwarder = TRUE;
4423 gpointer iter = NULL;
4426 if (klass->nested_in) {
4427 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4430 scope = resolution_scope_from_image (assembly, klass->image);
4431 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4432 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4433 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4436 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4439 alloc_table (table, table->rows);
4440 current_idx = table->next_idx;
4441 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4443 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4444 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4445 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4446 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4447 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4451 while ((nested = mono_class_get_nested_types (klass, &iter)))
4452 add_exported_type (assemblyb, assembly, nested, current_idx);
4456 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4462 if (!assemblyb->type_forwarders)
4465 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4466 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4471 type = mono_reflection_type_get_handle (t, &error);
4472 mono_error_assert_ok (&error);
4475 klass = mono_class_from_mono_type (type);
4477 add_exported_type (assemblyb, assembly, klass, 0);
4481 #define align_pointer(base,p)\
4483 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4485 (p) += 4 - (__diff & 3);\
4489 compare_constants (const void *a, const void *b)
4491 const guint32 *a_values = (const guint32 *)a;
4492 const guint32 *b_values = (const guint32 *)b;
4493 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4497 compare_semantics (const void *a, const void *b)
4499 const guint32 *a_values = (const guint32 *)a;
4500 const guint32 *b_values = (const guint32 *)b;
4501 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4504 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4508 compare_custom_attrs (const void *a, const void *b)
4510 const guint32 *a_values = (const guint32 *)a;
4511 const guint32 *b_values = (const guint32 *)b;
4513 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4517 compare_field_marshal (const void *a, const void *b)
4519 const guint32 *a_values = (const guint32 *)a;
4520 const guint32 *b_values = (const guint32 *)b;
4522 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4526 compare_nested (const void *a, const void *b)
4528 const guint32 *a_values = (const guint32 *)a;
4529 const guint32 *b_values = (const guint32 *)b;
4531 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4535 compare_genericparam (const void *a, const void *b)
4538 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4539 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4541 if ((*b_entry)->owner == (*a_entry)->owner) {
4542 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4543 mono_error_assert_ok (&error);
4544 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4545 mono_error_assert_ok (&error);
4547 mono_type_get_generic_param_num (a_type) -
4548 mono_type_get_generic_param_num (b_type);
4550 return (*a_entry)->owner - (*b_entry)->owner;
4554 compare_declsecurity_attrs (const void *a, const void *b)
4556 const guint32 *a_values = (const guint32 *)a;
4557 const guint32 *b_values = (const guint32 *)b;
4559 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4563 compare_interface_impl (const void *a, const void *b)
4565 const guint32 *a_values = (const guint32 *)a;
4566 const guint32 *b_values = (const guint32 *)b;
4568 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4572 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4576 pad_heap (MonoDynamicStream *sh)
4578 if (sh->index & 3) {
4579 int sz = 4 - (sh->index & 3);
4580 memset (sh->data + sh->index, 0, sz);
4587 MonoDynamicStream *stream;
4591 * build_compressed_metadata() fills in the blob of data that represents the
4592 * raw metadata as it will be saved in the PE file. The five streams are output
4593 * and the metadata tables are comnpressed from the guint32 array representation,
4594 * to the compressed on-disk format.
4597 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4599 MonoDynamicTable *table;
4601 guint64 valid_mask = 0;
4602 guint64 sorted_mask;
4603 guint32 heapt_size = 0;
4604 guint32 meta_size = 256; /* allow for header and other stuff */
4605 guint32 table_offset;
4606 guint32 ntables = 0;
4612 struct StreamDesc stream_desc [5];
4614 mono_error_init (error);
4616 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4617 for (i = 0; i < assembly->gen_params->len; i++) {
4618 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4619 if (!write_generic_param_entry (assembly, entry, error))
4623 stream_desc [0].name = "#~";
4624 stream_desc [0].stream = &assembly->tstream;
4625 stream_desc [1].name = "#Strings";
4626 stream_desc [1].stream = &assembly->sheap;
4627 stream_desc [2].name = "#US";
4628 stream_desc [2].stream = &assembly->us;
4629 stream_desc [3].name = "#Blob";
4630 stream_desc [3].stream = &assembly->blob;
4631 stream_desc [4].name = "#GUID";
4632 stream_desc [4].stream = &assembly->guid;
4634 /* tables that are sorted */
4635 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4636 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4637 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4638 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4639 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4640 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4641 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4643 /* Compute table sizes */
4644 /* the MonoImage has already been created in mono_image_basic_init() */
4645 meta = &assembly->image;
4647 /* sizes should be multiple of 4 */
4648 pad_heap (&assembly->blob);
4649 pad_heap (&assembly->guid);
4650 pad_heap (&assembly->sheap);
4651 pad_heap (&assembly->us);
4653 /* Setup the info used by compute_sizes () */
4654 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4655 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4656 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4658 meta_size += assembly->blob.index;
4659 meta_size += assembly->guid.index;
4660 meta_size += assembly->sheap.index;
4661 meta_size += assembly->us.index;
4663 for (i=0; i < MONO_TABLE_NUM; ++i)
4664 meta->tables [i].rows = assembly->tables [i].rows;
4666 for (i = 0; i < MONO_TABLE_NUM; i++){
4667 if (meta->tables [i].rows == 0)
4669 valid_mask |= (guint64)1 << i;
4671 meta->tables [i].row_size = mono_metadata_compute_size (
4672 meta, i, &meta->tables [i].size_bitfield);
4673 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4675 heapt_size += 24; /* #~ header size */
4676 heapt_size += ntables * 4;
4677 /* make multiple of 4 */
4680 meta_size += heapt_size;
4681 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4682 p = (unsigned char*)meta->raw_metadata;
4683 /* the metadata signature */
4684 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4685 /* version numbers and 4 bytes reserved */
4686 int16val = (guint16*)p;
4687 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4688 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4690 /* version string */
4691 int32val = (guint32*)p;
4692 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4694 memcpy (p, meta->version, strlen (meta->version));
4695 p += GUINT32_FROM_LE (*int32val);
4696 align_pointer (meta->raw_metadata, p);
4697 int16val = (guint16*)p;
4698 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4699 *int16val = GUINT16_TO_LE (5); /* number of streams */
4703 * write the stream info.
4705 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4706 table_offset += 3; table_offset &= ~3;
4708 assembly->tstream.index = heapt_size;
4709 for (i = 0; i < 5; ++i) {
4710 int32val = (guint32*)p;
4711 stream_desc [i].stream->offset = table_offset;
4712 *int32val++ = GUINT32_TO_LE (table_offset);
4713 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4714 table_offset += GUINT32_FROM_LE (*int32val);
4715 table_offset += 3; table_offset &= ~3;
4717 strcpy ((char*)p, stream_desc [i].name);
4718 p += strlen (stream_desc [i].name) + 1;
4719 align_pointer (meta->raw_metadata, p);
4722 * now copy the data, the table stream header and contents goes first.
4724 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4725 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4726 int32val = (guint32*)p;
4727 *int32val = GUINT32_TO_LE (0); /* reserved */
4730 *p++ = 2; /* version */
4733 if (meta->idx_string_wide)
4735 if (meta->idx_guid_wide)
4737 if (meta->idx_blob_wide)
4740 *p++ = 1; /* reserved */
4741 int64val = (guint64*)p;
4742 *int64val++ = GUINT64_TO_LE (valid_mask);
4743 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4745 int32val = (guint32*)p;
4746 for (i = 0; i < MONO_TABLE_NUM; i++){
4747 if (meta->tables [i].rows == 0)
4749 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4751 p = (unsigned char*)int32val;
4753 /* sort the tables that still need sorting */
4754 table = &assembly->tables [MONO_TABLE_CONSTANT];
4756 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4757 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4759 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4760 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4762 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4763 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4765 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4766 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4768 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4769 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4770 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4772 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4773 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4775 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4777 /* compress the tables */
4778 for (i = 0; i < MONO_TABLE_NUM; i++){
4781 guint32 bitfield = meta->tables [i].size_bitfield;
4782 if (!meta->tables [i].rows)
4784 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4785 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4786 meta->tables [i].base = (char*)p;
4787 for (row = 1; row <= meta->tables [i].rows; ++row) {
4788 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4789 for (col = 0; col < assembly->tables [i].columns; ++col) {
4790 switch (mono_metadata_table_size (bitfield, col)) {
4792 *p++ = values [col];
4795 *p++ = values [col] & 0xff;
4796 *p++ = (values [col] >> 8) & 0xff;
4799 *p++ = values [col] & 0xff;
4800 *p++ = (values [col] >> 8) & 0xff;
4801 *p++ = (values [col] >> 16) & 0xff;
4802 *p++ = (values [col] >> 24) & 0xff;
4805 g_assert_not_reached ();
4809 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4812 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4813 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4814 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4815 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4816 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4818 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4824 * Some tables in metadata need to be sorted according to some criteria, but
4825 * when methods and fields are first created with reflection, they may be assigned a token
4826 * that doesn't correspond to the final token they will get assigned after the sorting.
4827 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4828 * with the reflection objects that represent them. Once all the tables are set up, the
4829 * reflection objects will contains the correct table index. fixup_method() will fixup the
4830 * tokens for the method with ILGenerator @ilgen.
4833 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4835 guint32 code_idx = GPOINTER_TO_UINT (value);
4836 MonoReflectionILTokenInfo *iltoken;
4837 MonoReflectionFieldBuilder *field;
4838 MonoReflectionCtorBuilder *ctor;
4839 MonoReflectionMethodBuilder *method;
4840 MonoReflectionTypeBuilder *tb;
4841 MonoReflectionArrayMethod *am;
4843 unsigned char *target;
4845 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4846 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4847 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4848 switch (target [3]) {
4849 case MONO_TABLE_FIELD:
4850 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4851 field = (MonoReflectionFieldBuilder *)iltoken->member;
4852 idx = field->table_idx;
4853 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4854 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4855 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4857 g_assert_not_reached ();
4860 case MONO_TABLE_METHOD:
4861 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4862 method = (MonoReflectionMethodBuilder *)iltoken->member;
4863 idx = method->table_idx;
4864 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4865 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4866 idx = ctor->table_idx;
4867 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4868 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4869 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4870 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4872 g_assert_not_reached ();
4875 case MONO_TABLE_TYPEDEF:
4876 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4877 g_assert_not_reached ();
4878 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4879 idx = tb->table_idx;
4881 case MONO_TABLE_MEMBERREF:
4882 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4883 am = (MonoReflectionArrayMethod*)iltoken->member;
4884 idx = am->table_idx;
4885 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4886 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4887 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4888 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4889 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4890 g_assert (m->klass->generic_class || m->klass->generic_container);
4892 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4894 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4895 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4896 g_assert (is_field_on_inst (f));
4898 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4899 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4901 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4903 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4905 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4908 g_assert_not_reached ();
4911 case MONO_TABLE_METHODSPEC:
4912 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4913 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4914 g_assert (mono_method_signature (m)->generic_param_count);
4916 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4918 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4921 g_assert_not_reached ();
4925 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4927 target [0] = idx & 0xff;
4928 target [1] = (idx >> 8) & 0xff;
4929 target [2] = (idx >> 16) & 0xff;
4936 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4937 * value is not known when the table is emitted.
4940 fixup_cattrs (MonoDynamicImage *assembly)
4942 MonoDynamicTable *table;
4944 guint32 type, i, idx, token;
4947 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4949 for (i = 0; i < table->rows; ++i) {
4950 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4952 type = values [MONO_CUSTOM_ATTR_TYPE];
4953 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4954 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4955 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4956 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4959 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4960 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4961 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4962 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4963 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4964 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4965 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4966 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4973 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4975 MonoDynamicTable *table;
4978 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4980 alloc_table (table, table->rows);
4981 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4982 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4983 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4984 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4985 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4990 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4993 MonoDynamicTable *table;
4997 char *b = blob_size;
4999 guint32 idx, offset;
5001 if (rsrc->filename) {
5002 name = mono_string_to_utf8_checked (rsrc->filename, &error);
5003 mono_error_raise_exception (&error); /* FIXME don't raise here */
5004 sname = g_path_get_basename (name);
5006 table = &assembly->tables [MONO_TABLE_FILE];
5008 alloc_table (table, table->rows);
5009 values = table->values + table->next_idx * MONO_FILE_SIZE;
5010 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5011 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5014 mono_sha1_get_digest_from_file (name, hash);
5015 mono_metadata_encode_value (20, b, &b);
5016 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5017 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5019 idx = table->next_idx++;
5021 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5027 data = mono_array_addr (rsrc->data, char, 0);
5028 len = mono_array_length (rsrc->data);
5034 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5035 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5036 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5037 mono_image_add_stream_data (&assembly->resources, data, len);
5041 * The entry should be emitted into the MANIFESTRESOURCE table of
5042 * the main module, but that needs to reference the FILE table
5043 * which isn't emitted yet.
5050 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5054 set_version_from_string (MonoString *version, guint32 *values)
5057 gchar *ver, *p, *str;
5060 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5061 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5062 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5063 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5066 ver = str = mono_string_to_utf8_checked (version, &error);
5067 mono_error_raise_exception (&error); /* FIXME don't raise here */
5068 for (i = 0; i < 4; ++i) {
5069 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5075 /* handle Revision and Build */
5085 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5089 char *b = blob_size;
5094 len = mono_array_length (pkey);
5095 mono_metadata_encode_value (len, b, &b);
5096 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5097 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5099 assembly->public_key = (guint8 *)g_malloc (len);
5100 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5101 assembly->public_key_len = len;
5103 /* Special case: check for ECMA key (16 bytes) */
5104 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5105 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5106 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5107 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5108 /* minimum key size (in 2.0) is 384 bits */
5109 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5111 /* FIXME - verifier */
5112 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5113 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5115 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5121 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5123 MonoDynamicTable *table;
5124 MonoDynamicImage *assembly;
5125 MonoReflectionAssemblyBuilder *assemblyb;
5129 guint32 module_index;
5131 mono_error_init (error);
5133 assemblyb = moduleb->assemblyb;
5134 assembly = moduleb->dynamic_image;
5135 domain = mono_object_domain (assemblyb);
5137 /* Emit ASSEMBLY table */
5138 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5139 alloc_table (table, 1);
5140 values = table->values + MONO_ASSEMBLY_SIZE;
5141 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5142 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5143 if (assemblyb->culture) {
5144 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5146 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5148 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5149 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5150 set_version_from_string (assemblyb->version, values);
5152 /* Emit FILE + EXPORTED_TYPE table */
5154 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5156 MonoReflectionModuleBuilder *file_module =
5157 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5158 if (file_module != moduleb) {
5159 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5161 if (file_module->types) {
5162 for (j = 0; j < file_module->num_types; ++j) {
5163 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5164 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5165 return_if_nok (error);
5170 if (assemblyb->loaded_modules) {
5171 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5172 MonoReflectionModule *file_module =
5173 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5174 mono_image_fill_file_table (domain, file_module, assembly);
5176 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5179 if (assemblyb->type_forwarders)
5180 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5182 /* Emit MANIFESTRESOURCE table */
5184 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5186 MonoReflectionModuleBuilder *file_module =
5187 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5188 /* The table for the main module is emitted later */
5189 if (file_module != moduleb) {
5191 if (file_module->resources) {
5192 int len = mono_array_length (file_module->resources);
5193 for (j = 0; j < len; ++j) {
5194 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5195 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5202 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5205 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5206 * for the modulebuilder @moduleb.
5207 * At the end of the process, method and field tokens are fixed up and the
5208 * on-disk compressed metadata representation is created.
5209 * Return TRUE on success, or FALSE on failure and sets @error
5212 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5214 MonoDynamicTable *table;
5215 MonoDynamicImage *assembly;
5216 MonoReflectionAssemblyBuilder *assemblyb;
5222 mono_error_init (error);
5224 assemblyb = moduleb->assemblyb;
5225 assembly = moduleb->dynamic_image;
5226 domain = mono_object_domain (assemblyb);
5228 if (assembly->text_rva)
5231 assembly->text_rva = START_TEXT_RVA;
5233 if (moduleb->is_main) {
5234 mono_image_emit_manifest (moduleb, error);
5235 return_val_if_nok (error, FALSE);
5238 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5239 table->rows = 1; /* .<Module> */
5241 alloc_table (table, table->rows);
5243 * Set the first entry.
5245 values = table->values + table->columns;
5246 values [MONO_TYPEDEF_FLAGS] = 0;
5247 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5248 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5249 values [MONO_TYPEDEF_EXTENDS] = 0;
5250 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5251 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5254 * handle global methods
5255 * FIXME: test what to do when global methods are defined in multiple modules.
5257 if (moduleb->global_methods) {
5258 table = &assembly->tables [MONO_TABLE_METHOD];
5259 table->rows += mono_array_length (moduleb->global_methods);
5260 alloc_table (table, table->rows);
5261 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5262 if (!mono_image_get_method_info (
5263 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5267 if (moduleb->global_fields) {
5268 table = &assembly->tables [MONO_TABLE_FIELD];
5269 table->rows += mono_array_length (moduleb->global_fields);
5270 alloc_table (table, table->rows);
5271 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5272 mono_image_get_field_info (
5273 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5280 table = &assembly->tables [MONO_TABLE_MODULE];
5281 alloc_table (table, 1);
5282 mono_image_fill_module_table (domain, moduleb, assembly);
5284 /* Collect all types into a list sorted by their table_idx */
5285 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5288 for (i = 0; i < moduleb->num_types; ++i) {
5289 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5290 collect_types (&types, type);
5293 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5294 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5295 table->rows += mono_ptr_array_size (types);
5296 alloc_table (table, table->rows);
5299 * Emit type names + namespaces at one place inside the string heap,
5300 * so load_class_names () needs to touch fewer pages.
5302 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5303 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5304 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5306 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5307 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5308 string_heap_insert_mstring (&assembly->sheap, tb->name);
5311 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5312 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5313 if (!mono_image_get_type_info (domain, type, assembly, error))
5318 * table->rows is already set above and in mono_image_fill_module_table.
5320 /* add all the custom attributes at the end, once all the indexes are stable */
5321 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5324 /* CAS assembly permissions */
5325 if (assemblyb->permissions_minimum)
5326 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5327 if (assemblyb->permissions_optional)
5328 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5329 if (assemblyb->permissions_refused)
5330 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5332 if (!module_add_cattrs (assembly, moduleb, error))
5336 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5338 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5339 * the final tokens and don't need another fixup pass. */
5341 if (moduleb->global_methods) {
5342 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5343 MonoReflectionMethodBuilder *mb = mono_array_get (
5344 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5345 if (!mono_image_add_methodimpl (assembly, mb, error))
5350 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5351 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5352 if (type->methods) {
5353 for (j = 0; j < type->num_methods; ++j) {
5354 MonoReflectionMethodBuilder *mb = mono_array_get (
5355 type->methods, MonoReflectionMethodBuilder*, j);
5357 if (!mono_image_add_methodimpl (assembly, mb, error))
5363 fixup_cattrs (assembly);
5366 mono_ptr_array_destroy (types);
5369 return mono_error_ok (error);
5372 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5375 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5377 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5380 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5384 guint32 import_lookup_table;
5388 guint32 import_address_table_rva;
5396 #ifndef DISABLE_REFLECTION_EMIT
5399 * mono_image_insert_string:
5400 * @module: module builder object
5403 * Insert @str into the user string stream of @module.
5406 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5408 MonoDynamicImage *assembly;
5413 if (!module->dynamic_image)
5414 mono_image_module_basic_init (module);
5416 assembly = module->dynamic_image;
5418 if (assembly->save) {
5419 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5420 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5421 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5423 char *swapped = g_malloc (2 * mono_string_length (str));
5424 const char *p = (const char*)mono_string_chars (str);
5426 swap_with_size (swapped, p, 2, mono_string_length (str));
5427 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5431 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5433 mono_image_add_stream_data (&assembly->us, "", 1);
5435 idx = assembly->us.index ++;
5438 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5440 return MONO_TOKEN_STRING | idx;
5444 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5448 MonoMethodSignature *sig;
5450 mono_error_init (error);
5452 klass = obj->vtable->klass;
5453 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5454 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5455 MonoMethodSignature *old;
5456 guint32 sig_token, parent;
5459 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5461 nargs = mono_array_length (opt_param_types);
5462 old = mono_method_signature (method);
5463 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5465 sig->hasthis = old->hasthis;
5466 sig->explicit_this = old->explicit_this;
5467 sig->call_convention = old->call_convention;
5468 sig->generic_param_count = old->generic_param_count;
5469 sig->param_count = old->param_count + nargs;
5470 sig->sentinelpos = old->param_count;
5471 sig->ret = old->ret;
5473 for (i = 0; i < old->param_count; i++)
5474 sig->params [i] = old->params [i];
5476 for (i = 0; i < nargs; i++) {
5477 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5478 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5479 if (!is_ok (error)) goto fail;
5482 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5483 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5484 parent >>= MONO_TYPEDEFORREF_BITS;
5486 parent <<= MONO_MEMBERREF_PARENT_BITS;
5487 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5489 sig_token = method_encode_signature (assembly, sig);
5490 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5491 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5492 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5493 ReflectionMethodBuilder rmb;
5494 guint32 parent, sig_token;
5495 int nopt_args, nparams, ngparams, i;
5497 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5500 rmb.opt_types = opt_param_types;
5501 nopt_args = mono_array_length (opt_param_types);
5503 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5504 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5505 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5507 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5508 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5509 sig->call_convention = rmb.call_conv;
5510 sig->generic_param_count = ngparams;
5511 sig->param_count = nparams + nopt_args;
5512 sig->sentinelpos = nparams;
5513 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5514 if (!is_ok (error)) goto fail;
5516 for (i = 0; i < nparams; i++) {
5517 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5518 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5519 if (!is_ok (error)) goto fail;
5522 for (i = 0; i < nopt_args; i++) {
5523 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5524 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5525 if (!is_ok (error)) goto fail;
5528 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5532 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5533 if (!mono_error_ok (error))
5535 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5537 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5538 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5540 char *name = mono_string_to_utf8_checked (rmb.name, error);
5541 if (!is_ok (error)) goto fail;
5542 token = mono_image_get_varargs_method_token (
5543 assembly, parent, name, sig_token);
5546 g_error ("requested method token for %s\n", klass->name);
5549 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5550 register_dyn_token (assembly, token, obj);
5553 g_assert (!mono_error_ok (error));
5558 * mono_image_create_token:
5559 * @assembly: a dynamic assembly
5561 * @register_token: Whenever to register the token in the assembly->tokens hash.
5563 * Get a token to insert in the IL code stream for the given MemberInfo.
5564 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5565 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5569 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5570 gboolean create_open_instance, gboolean register_token,
5576 mono_error_init (error);
5578 klass = obj->vtable->klass;
5580 /* Check for user defined reflection objects */
5581 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5582 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5583 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5587 if (strcmp (klass->name, "MethodBuilder") == 0) {
5588 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5589 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5591 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5592 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5594 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5595 if (!mono_error_ok (error))
5598 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5599 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5600 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5601 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5603 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5604 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5606 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5607 if (!mono_error_ok (error))
5610 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5611 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5612 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5613 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5614 if (tb->generic_params) {
5615 token = mono_image_get_generic_field_token (assembly, fb, error);
5616 return_val_if_nok (error, 0);
5618 if (tb->module->dynamic_image == assembly) {
5619 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5621 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5624 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5625 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5626 if (create_open_instance && tb->generic_params) {
5628 init_type_builder_generics (obj, error);
5629 return_val_if_nok (error, 0);
5630 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5631 return_val_if_nok (error, 0);
5632 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5633 token = mono_metadata_token_from_dor (token);
5634 } else if (tb->module->dynamic_image == assembly) {
5635 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5638 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5639 return_val_if_nok (error, 0);
5640 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5642 } else if (strcmp (klass->name, "RuntimeType") == 0) {
5643 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5644 return_val_if_nok (error, 0);
5645 MonoClass *mc = mono_class_from_mono_type (type);
5646 token = mono_metadata_token_from_dor (
5647 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5648 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5649 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5650 return_val_if_nok (error, 0);
5651 token = mono_metadata_token_from_dor (
5652 mono_image_typedef_or_ref (assembly, type));
5653 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5654 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5655 return_val_if_nok (error, 0);
5656 token = mono_metadata_token_from_dor (
5657 mono_image_typedef_or_ref (assembly, type));
5658 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5659 strcmp (klass->name, "MonoMethod") == 0 ||
5660 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5661 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5662 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5663 if (m->method->is_inflated) {
5664 if (create_open_instance)
5665 token = mono_image_get_methodspec_token (assembly, m->method);
5667 token = mono_image_get_inflated_method_token (assembly, m->method);
5668 } else if ((m->method->klass->image == &assembly->image) &&
5669 !m->method->klass->generic_class) {
5670 static guint32 method_table_idx = 0xffffff;
5671 if (m->method->klass->wastypebuilder) {
5672 /* we use the same token as the one that was assigned
5673 * to the Methodbuilder.
5674 * FIXME: do the equivalent for Fields.
5676 token = m->method->token;
5679 * Each token should have a unique index, but the indexes are
5680 * assigned by managed code, so we don't know about them. An
5681 * easy solution is to count backwards...
5683 method_table_idx --;
5684 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5687 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5689 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5690 } else if (strcmp (klass->name, "MonoField") == 0) {
5691 MonoReflectionField *f = (MonoReflectionField *)obj;
5692 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5693 static guint32 field_table_idx = 0xffffff;
5695 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5697 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5699 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5700 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5701 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5702 token = mono_image_get_array_token (assembly, m, error);
5703 return_val_if_nok (error, 0);
5704 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5705 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5706 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5707 return_val_if_nok (error, 0);
5708 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5709 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5710 return_val_if_nok (error, 0);
5711 token = mono_metadata_token_from_dor (
5712 mono_image_typedef_or_ref (assembly, type));
5713 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5714 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5715 token = mono_image_get_field_on_inst_token (assembly, f, error);
5716 return_val_if_nok (error, 0);
5717 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5718 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5719 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5720 if (!mono_error_ok (error))
5722 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5723 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5724 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5725 if (!mono_error_ok (error))
5727 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5728 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5729 return_val_if_nok (error, 0);
5730 token = mono_metadata_token_from_dor (
5731 mono_image_typedef_or_ref (assembly, type));
5733 g_error ("requested token for %s\n", klass->name);
5737 mono_image_register_token (assembly, token, obj);
5743 * mono_image_register_token:
5745 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5746 * the Module.ResolveXXXToken () methods to work.
5749 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5753 dynamic_image_lock (assembly);
5754 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5756 /* There could be multiple MethodInfo objects with the same token */
5757 //g_assert (prev == obj);
5759 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5761 dynamic_image_unlock (assembly);
5764 static MonoDynamicImage*
5765 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5767 static const guchar entrycode [16] = {0xff, 0x25, 0};
5768 MonoDynamicImage *image;
5771 const char *version;
5773 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5774 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5776 version = mono_get_runtime_info ()->runtime_version;
5779 /* The MonoGHashTable's need GC tracking */
5780 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5782 image = g_new0 (MonoDynamicImage, 1);
5785 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5787 /*g_print ("created image %p\n", image);*/
5788 /* keep in sync with image.c */
5789 image->image.name = assembly_name;
5790 image->image.assembly_name = image->image.name; /* they may be different */
5791 image->image.module_name = module_name;
5792 image->image.version = g_strdup (version);
5793 image->image.md_version_major = 1;
5794 image->image.md_version_minor = 1;
5795 image->image.dynamic = TRUE;
5797 image->image.references = g_new0 (MonoAssembly*, 1);
5798 image->image.references [0] = NULL;
5800 mono_image_init (&image->image);
5802 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");
5803 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5804 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5805 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5806 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5807 image->handleref = g_hash_table_new (NULL, NULL);
5808 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");
5809 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5810 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");
5811 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");
5812 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5813 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5814 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5815 image->gen_params = g_ptr_array_new ();
5816 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5818 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5819 string_heap_init (&image->sheap);
5820 mono_image_add_stream_data (&image->us, "", 1);
5821 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5822 /* import tables... */
5823 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5824 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5825 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5826 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5827 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5828 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5829 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5830 stream_data_align (&image->code);
5832 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5834 for (i=0; i < MONO_TABLE_NUM; ++i) {
5835 image->tables [i].next_idx = 1;
5836 image->tables [i].columns = table_sizes [i];
5839 image->image.assembly = (MonoAssembly*)assembly;
5840 image->run = assembly->run;
5841 image->save = assembly->save;
5842 image->pe_kind = 0x1; /* ILOnly */
5843 image->machine = 0x14c; /* I386 */
5845 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5847 dynamic_images_lock ();
5849 if (!dynamic_images)
5850 dynamic_images = g_ptr_array_new ();
5852 g_ptr_array_add (dynamic_images, image);
5854 dynamic_images_unlock ();
5861 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5867 release_hashtable (MonoGHashTable **hash)
5870 mono_g_hash_table_destroy (*hash);
5876 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5878 release_hashtable (&image->token_fixups);
5879 release_hashtable (&image->handleref_managed);
5880 release_hashtable (&image->tokens);
5881 release_hashtable (&image->remapped_tokens);
5882 release_hashtable (&image->generic_def_objects);
5883 release_hashtable (&image->methodspec);
5886 // Free dynamic image pass one: Free resources but not image itself
5888 mono_dynamic_image_free (MonoDynamicImage *image)
5890 MonoDynamicImage *di = image;
5895 mono_g_hash_table_destroy (di->methodspec);
5897 g_hash_table_destroy (di->typespec);
5899 g_hash_table_destroy (di->typeref);
5901 g_hash_table_destroy (di->handleref);
5902 if (di->handleref_managed)
5903 mono_g_hash_table_destroy (di->handleref_managed);
5905 mono_g_hash_table_destroy (di->tokens);
5906 if (di->remapped_tokens)
5907 mono_g_hash_table_destroy (di->remapped_tokens);
5908 if (di->generic_def_objects)
5909 mono_g_hash_table_destroy (di->generic_def_objects);
5910 if (di->blob_cache) {
5911 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5912 g_hash_table_destroy (di->blob_cache);
5914 if (di->standalonesig_cache)
5915 g_hash_table_destroy (di->standalonesig_cache);
5916 for (list = di->array_methods; list; list = list->next) {
5917 ArrayMethod *am = (ArrayMethod *)list->data;
5922 g_list_free (di->array_methods);
5923 if (di->gen_params) {
5924 for (i = 0; i < di->gen_params->len; i++) {
5925 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5926 mono_gc_deregister_root ((char*) &entry->gparam);
5929 g_ptr_array_free (di->gen_params, TRUE);
5931 if (di->token_fixups)
5932 mono_g_hash_table_destroy (di->token_fixups);
5933 if (di->method_to_table_idx)
5934 g_hash_table_destroy (di->method_to_table_idx);
5935 if (di->field_to_table_idx)
5936 g_hash_table_destroy (di->field_to_table_idx);
5937 if (di->method_aux_hash)
5938 g_hash_table_destroy (di->method_aux_hash);
5939 if (di->vararg_aux_hash)
5940 g_hash_table_destroy (di->vararg_aux_hash);
5941 g_free (di->strong_name);
5942 g_free (di->win32_res);
5944 g_free (di->public_key);
5946 /*g_print ("string heap destroy for image %p\n", di);*/
5947 mono_dynamic_stream_reset (&di->sheap);
5948 mono_dynamic_stream_reset (&di->code);
5949 mono_dynamic_stream_reset (&di->resources);
5950 mono_dynamic_stream_reset (&di->us);
5951 mono_dynamic_stream_reset (&di->blob);
5952 mono_dynamic_stream_reset (&di->tstream);
5953 mono_dynamic_stream_reset (&di->guid);
5954 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5955 g_free (di->tables [i].values);
5958 dynamic_images_lock ();
5961 g_ptr_array_remove (dynamic_images, di);
5963 dynamic_images_unlock ();
5966 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5968 mono_dynamic_image_free_image (MonoDynamicImage *image)
5970 /* See create_dynamic_mono_image () */
5972 /* Allocated using GC_MALLOC */
5978 #ifndef DISABLE_REFLECTION_EMIT
5981 * mono_image_basic_init:
5982 * @assembly: an assembly builder object
5984 * Create the MonoImage that represents the assembly builder and setup some
5985 * of the helper hash table and the basic metadata streams.
5988 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5991 MonoDynamicAssembly *assembly;
5992 MonoDynamicImage *image;
5993 MonoDomain *domain = mono_object_domain (assemblyb);
5995 if (assemblyb->dynamic_assembly)
5999 /* assembly->assembly.image might be GC allocated */
6000 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6002 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6005 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6007 assembly->assembly.ref_count = 1;
6008 assembly->assembly.dynamic = TRUE;
6009 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6010 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6011 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6012 mono_error_raise_exception (&error); /* FIXME don't raise here */
6013 if (assemblyb->culture) {
6014 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6015 mono_error_raise_exception (&error); /* FIXME don't raise here */
6017 assembly->assembly.aname.culture = g_strdup ("");
6019 if (assemblyb->version) {
6020 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6021 mono_error_raise_exception (&error); /* FIXME don't raise here */
6022 char **version = g_strsplit (vstr, ".", 4);
6023 char **parts = version;
6024 assembly->assembly.aname.major = atoi (*parts++);
6025 assembly->assembly.aname.minor = atoi (*parts++);
6026 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6027 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6029 g_strfreev (version);
6032 assembly->assembly.aname.major = 0;
6033 assembly->assembly.aname.minor = 0;
6034 assembly->assembly.aname.build = 0;
6035 assembly->assembly.aname.revision = 0;
6038 assembly->run = assemblyb->access != 2;
6039 assembly->save = assemblyb->access != 1;
6040 assembly->domain = domain;
6042 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6043 mono_error_raise_exception (&error); /* FIXME don't raise here */
6044 image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6045 image->initial_image = TRUE;
6046 assembly->assembly.aname.name = image->image.name;
6047 assembly->assembly.image = &image->image;
6048 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6049 /* -1 to correct for the trailing NULL byte */
6050 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6051 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6053 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6056 mono_domain_assemblies_lock (domain);
6057 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6058 mono_domain_assemblies_unlock (domain);
6060 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6062 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6064 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6067 #endif /* !DISABLE_REFLECTION_EMIT */
6069 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6072 calc_section_size (MonoDynamicImage *assembly)
6076 /* alignment constraints */
6077 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6078 g_assert ((assembly->code.index % 4) == 0);
6079 assembly->meta_size += 3;
6080 assembly->meta_size &= ~3;
6081 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6082 g_assert ((assembly->resources.index % 4) == 0);
6084 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6085 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6088 if (assembly->win32_res) {
6089 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6091 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6092 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6096 assembly->sections [MONO_SECTION_RELOC].size = 12;
6097 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6107 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6111 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6113 ResTreeNode *t1 = (ResTreeNode*)a;
6114 ResTreeNode *t2 = (ResTreeNode*)b;
6116 return t1->id - t2->id;
6120 * resource_tree_create:
6122 * Organize the resources into a resource tree.
6124 static ResTreeNode *
6125 resource_tree_create (MonoArray *win32_resources)
6127 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6131 tree = g_new0 (ResTreeNode, 1);
6133 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6134 MonoReflectionWin32Resource *win32_res =
6135 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6139 /* FIXME: BUG: this stores managed references in unmanaged memory */
6140 lang_node = g_new0 (ResTreeNode, 1);
6141 lang_node->id = win32_res->lang_id;
6142 lang_node->win32_res = win32_res;
6144 /* Create type node if neccesary */
6146 for (l = tree->children; l; l = l->next)
6147 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6148 type_node = (ResTreeNode*)l->data;
6153 type_node = g_new0 (ResTreeNode, 1);
6154 type_node->id = win32_res->res_type;
6157 * The resource types have to be sorted otherwise
6158 * Windows Explorer can't display the version information.
6160 tree->children = g_slist_insert_sorted (tree->children,
6161 type_node, resource_tree_compare_by_id);
6164 /* Create res node if neccesary */
6166 for (l = type_node->children; l; l = l->next)
6167 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6168 res_node = (ResTreeNode*)l->data;
6173 res_node = g_new0 (ResTreeNode, 1);
6174 res_node->id = win32_res->res_id;
6175 type_node->children = g_slist_append (type_node->children, res_node);
6178 res_node->children = g_slist_append (res_node->children, lang_node);
6185 * resource_tree_encode:
6187 * Encode the resource tree into the format used in the PE file.
6190 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6193 MonoPEResourceDir dir;
6194 MonoPEResourceDirEntry dir_entry;
6195 MonoPEResourceDataEntry data_entry;
6197 guint32 res_id_entries;
6200 * For the format of the resource directory, see the article
6201 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6205 memset (&dir, 0, sizeof (dir));
6206 memset (&dir_entry, 0, sizeof (dir_entry));
6207 memset (&data_entry, 0, sizeof (data_entry));
6209 g_assert (sizeof (dir) == 16);
6210 g_assert (sizeof (dir_entry) == 8);
6211 g_assert (sizeof (data_entry) == 16);
6213 node->offset = p - begin;
6215 /* IMAGE_RESOURCE_DIRECTORY */
6216 res_id_entries = g_slist_length (node->children);
6217 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6219 memcpy (p, &dir, sizeof (dir));
6222 /* Reserve space for entries */
6224 p += sizeof (dir_entry) * res_id_entries;
6226 /* Write children */
6227 for (l = node->children; l; l = l->next) {
6228 ResTreeNode *child = (ResTreeNode*)l->data;
6230 if (child->win32_res) {
6233 child->offset = p - begin;
6235 /* IMAGE_RESOURCE_DATA_ENTRY */
6236 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6237 size = mono_array_length (child->win32_res->res_data);
6238 data_entry.rde_size = GUINT32_TO_LE (size);
6240 memcpy (p, &data_entry, sizeof (data_entry));
6241 p += sizeof (data_entry);
6243 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6246 resource_tree_encode (child, begin, p, &p);
6250 /* IMAGE_RESOURCE_ENTRY */
6251 for (l = node->children; l; l = l->next) {
6252 ResTreeNode *child = (ResTreeNode*)l->data;
6254 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6255 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6257 memcpy (entries, &dir_entry, sizeof (dir_entry));
6258 entries += sizeof (dir_entry);
6265 resource_tree_free (ResTreeNode * node)
6268 for (list = node->children; list; list = list->next)
6269 resource_tree_free ((ResTreeNode*)list->data);
6270 g_slist_free(node->children);
6275 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6280 MonoReflectionWin32Resource *win32_res;
6283 if (!assemblyb->win32_resources)
6287 * Resources are stored in a three level tree inside the PE file.
6288 * - level one contains a node for each type of resource
6289 * - level two contains a node for each resource
6290 * - level three contains a node for each instance of a resource for a
6291 * specific language.
6294 tree = resource_tree_create (assemblyb->win32_resources);
6296 /* Estimate the size of the encoded tree */
6298 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6299 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6300 size += mono_array_length (win32_res->res_data);
6302 /* Directory structure */
6303 size += mono_array_length (assemblyb->win32_resources) * 256;
6304 p = buf = (char *)g_malloc (size);
6306 resource_tree_encode (tree, p, p, &p);
6308 g_assert (p - buf <= size);
6310 assembly->win32_res = (char *)g_malloc (p - buf);
6311 assembly->win32_res_size = p - buf;
6312 memcpy (assembly->win32_res, buf, p - buf);
6315 resource_tree_free (tree);
6319 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6321 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6324 p += sizeof (MonoPEResourceDir);
6325 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6326 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6327 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6328 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6329 fixup_resource_directory (res_section, child, rva);
6331 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6332 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6335 p += sizeof (MonoPEResourceDirEntry);
6340 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6343 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6344 g_error ("WriteFile returned %d\n", GetLastError ());
6348 * mono_image_create_pefile:
6349 * @mb: a module builder object
6351 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6352 * assembly->pefile where it can be easily retrieved later in chunks.
6355 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6357 MonoMSDOSHeader *msdos;
6358 MonoDotNetHeader *header;
6359 MonoSectionTable *section;
6360 MonoCLIHeader *cli_header;
6361 guint32 size, image_size, virtual_base, text_offset;
6362 guint32 header_start, section_start, file_offset, virtual_offset;
6363 MonoDynamicImage *assembly;
6364 MonoReflectionAssemblyBuilder *assemblyb;
6365 MonoDynamicStream pefile_stream = {0};
6366 MonoDynamicStream *pefile = &pefile_stream;
6368 guint32 *rva, value;
6370 static const unsigned char msheader[] = {
6371 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6372 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6375 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6376 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6377 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6378 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6381 mono_error_init (error);
6383 assemblyb = mb->assemblyb;
6385 mono_image_basic_init (assemblyb);
6386 assembly = mb->dynamic_image;
6388 assembly->pe_kind = assemblyb->pe_kind;
6389 assembly->machine = assemblyb->machine;
6390 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6391 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6393 if (!mono_image_build_metadata (mb, error))
6397 if (mb->is_main && assemblyb->resources) {
6398 int len = mono_array_length (assemblyb->resources);
6399 for (i = 0; i < len; ++i)
6400 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6403 if (mb->resources) {
6404 int len = mono_array_length (mb->resources);
6405 for (i = 0; i < len; ++i)
6406 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6409 if (!build_compressed_metadata (assembly, error))
6413 assembly_add_win32_resources (assembly, assemblyb);
6415 nsections = calc_section_size (assembly);
6417 /* The DOS header and stub */
6418 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6419 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6421 /* the dotnet header */
6422 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6424 /* the section tables */
6425 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6427 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6428 virtual_offset = VIRT_ALIGN;
6431 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6432 if (!assembly->sections [i].size)
6435 file_offset += FILE_ALIGN - 1;
6436 file_offset &= ~(FILE_ALIGN - 1);
6437 virtual_offset += VIRT_ALIGN - 1;
6438 virtual_offset &= ~(VIRT_ALIGN - 1);
6440 assembly->sections [i].offset = file_offset;
6441 assembly->sections [i].rva = virtual_offset;
6443 file_offset += assembly->sections [i].size;
6444 virtual_offset += assembly->sections [i].size;
6445 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6448 file_offset += FILE_ALIGN - 1;
6449 file_offset &= ~(FILE_ALIGN - 1);
6451 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6453 /* back-patch info */
6454 msdos = (MonoMSDOSHeader*)pefile->data;
6455 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6457 header = (MonoDotNetHeader*)(pefile->data + header_start);
6458 header->pesig [0] = 'P';
6459 header->pesig [1] = 'E';
6461 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6462 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6463 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6464 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6465 if (assemblyb->pekind == 1) {
6467 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6470 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6473 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6475 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6476 header->pe.pe_major = 6;
6477 header->pe.pe_minor = 0;
6478 size = assembly->sections [MONO_SECTION_TEXT].size;
6479 size += FILE_ALIGN - 1;
6480 size &= ~(FILE_ALIGN - 1);
6481 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6482 size = assembly->sections [MONO_SECTION_RSRC].size;
6483 size += FILE_ALIGN - 1;
6484 size &= ~(FILE_ALIGN - 1);
6485 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6486 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6487 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6488 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6489 /* pe_rva_entry_point always at the beginning of the text section */
6490 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6492 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6493 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6494 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6495 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6496 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6497 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6498 size = section_start;
6499 size += FILE_ALIGN - 1;
6500 size &= ~(FILE_ALIGN - 1);
6501 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6503 size += VIRT_ALIGN - 1;
6504 size &= ~(VIRT_ALIGN - 1);
6505 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6508 // Translate the PEFileKind value to the value expected by the Windows loader
6514 // PEFileKinds.Dll == 1
6515 // PEFileKinds.ConsoleApplication == 2
6516 // PEFileKinds.WindowApplication == 3
6519 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6520 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6522 if (assemblyb->pekind == 3)
6527 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6529 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6530 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6531 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6532 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6533 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6534 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6536 /* fill data directory entries */
6538 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6539 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6541 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6542 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6544 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6545 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6546 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6547 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6548 /* patch entrypoint name */
6549 if (assemblyb->pekind == 1)
6550 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6552 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6553 /* patch imported function RVA name */
6554 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6555 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6557 /* the import table */
6558 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6559 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6560 /* patch imported dll RVA name and other entries in the dir */
6561 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6562 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6563 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6564 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6565 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6566 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6568 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6569 value = (assembly->text_rva + assembly->imp_names_offset);
6570 *p++ = (value) & 0xff;
6571 *p++ = (value >> 8) & (0xff);
6572 *p++ = (value >> 16) & (0xff);
6573 *p++ = (value >> 24) & (0xff);
6575 /* the CLI header info */
6576 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6577 cli_header->ch_size = GUINT32_FROM_LE (72);
6578 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6579 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6580 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6581 if (assemblyb->entry_point) {
6582 guint32 table_idx = 0;
6583 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6584 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6585 table_idx = methodb->table_idx;
6587 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6589 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6591 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6593 /* The embedded managed resources */
6594 text_offset = assembly->text_rva + assembly->code.index;
6595 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6596 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6597 text_offset += assembly->resources.index;
6598 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6599 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6600 text_offset += assembly->meta_size;
6601 if (assembly->strong_name_size) {
6602 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6603 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6604 text_offset += assembly->strong_name_size;
6607 /* write the section tables and section content */
6608 section = (MonoSectionTable*)(pefile->data + section_start);
6609 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6610 static const char section_names [][7] = {
6611 ".text", ".rsrc", ".reloc"
6613 if (!assembly->sections [i].size)
6615 strcpy (section->st_name, section_names [i]);
6616 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6617 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6618 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6619 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6620 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6621 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6622 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6626 checked_write_file (file, pefile->data, pefile->index);
6628 mono_dynamic_stream_reset (pefile);
6630 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6631 if (!assembly->sections [i].size)
6634 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6635 g_error ("SetFilePointer returned %d\n", GetLastError ());
6638 case MONO_SECTION_TEXT:
6639 /* patch entry point */
6640 p = (guchar*)(assembly->code.data + 2);
6641 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6642 *p++ = (value) & 0xff;
6643 *p++ = (value >> 8) & 0xff;
6644 *p++ = (value >> 16) & 0xff;
6645 *p++ = (value >> 24) & 0xff;
6647 checked_write_file (file, assembly->code.data, assembly->code.index);
6648 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6649 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6650 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6653 g_free (assembly->image.raw_metadata);
6655 case MONO_SECTION_RELOC: {
6659 guint16 type_and_offset;
6663 g_assert (sizeof (reloc) == 12);
6665 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6666 reloc.block_size = GUINT32_FROM_LE (12);
6669 * the entrypoint is always at the start of the text section
6670 * 3 is IMAGE_REL_BASED_HIGHLOW
6671 * 2 is patch_size_rva - text_rva
6673 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6676 checked_write_file (file, &reloc, sizeof (reloc));
6680 case MONO_SECTION_RSRC:
6681 if (assembly->win32_res) {
6683 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6684 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6685 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6689 g_assert_not_reached ();
6693 /* check that the file is properly padded */
6694 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6695 g_error ("SetFilePointer returned %d\n", GetLastError ());
6696 if (! SetEndOfFile (file))
6697 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6699 mono_dynamic_stream_reset (&assembly->code);
6700 mono_dynamic_stream_reset (&assembly->us);
6701 mono_dynamic_stream_reset (&assembly->blob);
6702 mono_dynamic_stream_reset (&assembly->guid);
6703 mono_dynamic_stream_reset (&assembly->sheap);
6705 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6706 g_hash_table_destroy (assembly->blob_cache);
6707 assembly->blob_cache = NULL;
6712 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6715 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6717 g_assert_not_reached ();
6720 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6722 #ifndef DISABLE_REFLECTION_EMIT
6724 MonoReflectionModule *
6725 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6729 MonoImageOpenStatus status;
6730 MonoDynamicAssembly *assembly;
6731 guint32 module_count;
6732 MonoImage **new_modules;
6733 gboolean *new_modules_loaded;
6735 mono_error_init (error);
6737 name = mono_string_to_utf8_checked (fileName, error);
6738 return_val_if_nok (error, NULL);
6740 image = mono_image_open (name, &status);
6742 if (status == MONO_IMAGE_ERROR_ERRNO)
6743 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6745 mono_error_set_bad_image_name (error, name, NULL);
6752 assembly = ab->dynamic_assembly;
6753 image->assembly = (MonoAssembly*)assembly;
6755 module_count = image->assembly->image->module_count;
6756 new_modules = g_new0 (MonoImage *, module_count + 1);
6757 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6759 if (image->assembly->image->modules)
6760 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6761 if (image->assembly->image->modules_loaded)
6762 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6763 new_modules [module_count] = image;
6764 new_modules_loaded [module_count] = TRUE;
6765 mono_image_addref (image);
6767 g_free (image->assembly->image->modules);
6768 image->assembly->image->modules = new_modules;
6769 image->assembly->image->modules_loaded = new_modules_loaded;
6770 image->assembly->image->module_count ++;
6772 mono_assembly_load_references (image, &status);
6774 mono_image_close (image);
6775 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6779 return mono_module_get_object_checked (mono_domain_get (), image, error);
6782 #endif /* DISABLE_REFLECTION_EMIT */
6785 * We need to return always the same object for MethodInfo, FieldInfo etc..
6786 * but we need to consider the reflected type.
6787 * type uses a different hash, since it uses custom hash/equal functions.
6792 MonoClass *refclass;
6796 reflected_equal (gconstpointer a, gconstpointer b) {
6797 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6798 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6800 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6804 reflected_hash (gconstpointer a) {
6805 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6806 return mono_aligned_addr_hash (ea->item);
6809 #define CHECK_OBJECT(t,p,k) \
6815 mono_domain_lock (domain); \
6816 if (!domain->refobject_hash) \
6817 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"); \
6818 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6819 mono_domain_unlock (domain); \
6822 mono_domain_unlock (domain); \
6825 #ifdef HAVE_BOEHM_GC
6826 /* ReflectedEntry doesn't need to be GC tracked */
6827 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6828 #define FREE_REFENTRY(entry) g_free ((entry))
6829 #define REFENTRY_REQUIRES_CLEANUP
6831 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6833 #define FREE_REFENTRY(entry)
6836 #define CACHE_OBJECT(t,p,o,k) \
6839 ReflectedEntry pe; \
6841 pe.refclass = (k); \
6842 mono_domain_lock (domain); \
6843 if (!domain->refobject_hash) \
6844 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"); \
6845 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6847 ReflectedEntry *e = ALLOC_REFENTRY; \
6849 e->refclass = (k); \
6850 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6853 mono_domain_unlock (domain); \
6858 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6860 mono_domain_lock (domain);
6861 if (domain->refobject_hash) {
6863 gpointer orig_pe, orig_value;
6866 pe.refclass = klass;
6867 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6868 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6869 FREE_REFENTRY (orig_pe);
6872 mono_domain_unlock (domain);
6875 #ifdef REFENTRY_REQUIRES_CLEANUP
6877 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6879 FREE_REFENTRY (key);
6884 mono_reflection_cleanup_domain (MonoDomain *domain)
6886 if (domain->refobject_hash) {
6887 /*let's avoid scanning the whole hashtable if not needed*/
6888 #ifdef REFENTRY_REQUIRES_CLEANUP
6889 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6891 mono_g_hash_table_destroy (domain->refobject_hash);
6892 domain->refobject_hash = NULL;
6896 #ifndef DISABLE_REFLECTION_EMIT
6898 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6900 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6904 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6906 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6910 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6912 MonoDynamicImage *image = moduleb->dynamic_image;
6913 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6914 mono_error_init (error);
6917 MonoImage **new_modules;
6919 char *name, *fqname;
6921 * FIXME: we already created an image in mono_image_basic_init (), but
6922 * we don't know which module it belongs to, since that is only
6923 * determined at assembly save time.
6925 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6926 name = mono_string_to_utf8_checked (ab->name, error);
6927 return_val_if_nok (error, FALSE);
6928 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6929 if (!is_ok (error)) {
6933 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6935 moduleb->module.image = &image->image;
6936 moduleb->dynamic_image = image;
6937 register_module (mono_object_domain (moduleb), moduleb, image);
6939 /* register the module with the assembly */
6940 ass = ab->dynamic_assembly->assembly.image;
6941 module_count = ass->module_count;
6942 new_modules = g_new0 (MonoImage *, module_count + 1);
6945 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6946 new_modules [module_count] = &image->image;
6947 mono_image_addref (&image->image);
6949 g_free (ass->modules);
6950 ass->modules = new_modules;
6951 ass->module_count ++;
6957 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6960 (void) image_module_basic_init (moduleb, &error);
6961 mono_error_set_pending_exception (&error);
6965 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6967 MonoDynamicImage *image = moduleb->dynamic_image;
6969 g_assert (type->type);
6970 image->wrappers_type = mono_class_from_mono_type (type->type);
6976 * mono_assembly_get_object:
6977 * @domain: an app domain
6978 * @assembly: an assembly
6980 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6982 MonoReflectionAssembly*
6983 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6986 MonoReflectionAssembly *result;
6987 result = mono_assembly_get_object_checked (domain, assembly, &error);
6988 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6992 * mono_assembly_get_object_checked:
6993 * @domain: an app domain
6994 * @assembly: an assembly
6996 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6998 MonoReflectionAssembly*
6999 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7001 MonoReflectionAssembly *res;
7003 mono_error_init (error);
7005 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7006 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7009 res->assembly = assembly;
7011 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7016 MonoReflectionModule*
7017 mono_module_get_object (MonoDomain *domain, MonoImage *image)
7020 MonoReflectionModule *result;
7021 result = mono_module_get_object_checked (domain, image, &error);
7022 mono_error_cleanup (&error);
7026 MonoReflectionModule*
7027 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7029 MonoReflectionModule *res;
7032 mono_error_init (error);
7033 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7034 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7039 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7042 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7044 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7045 basename = g_path_get_basename (image->name);
7046 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7047 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7051 if (image->assembly->image == image) {
7052 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7056 if (image->assembly->image->modules) {
7057 for (i = 0; i < image->assembly->image->module_count; i++) {
7058 if (image->assembly->image->modules [i] == image)
7059 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7061 g_assert (res->token);
7065 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7068 MonoReflectionModule*
7069 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7072 MonoReflectionModule *result;
7073 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7074 mono_error_cleanup (&error);
7078 MonoReflectionModule*
7079 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7081 MonoReflectionModule *res;
7082 MonoTableInfo *table;
7083 guint32 cols [MONO_FILE_SIZE];
7085 guint32 i, name_idx;
7088 mono_error_init (error);
7090 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7094 table = &image->tables [MONO_TABLE_FILE];
7095 g_assert (table_index < table->rows);
7096 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7099 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7102 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7103 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7105 /* Check whenever the row has a corresponding row in the moduleref table */
7106 table = &image->tables [MONO_TABLE_MODULEREF];
7107 for (i = 0; i < table->rows; ++i) {
7108 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7109 val = mono_metadata_string_heap (image, name_idx);
7110 if (strcmp (val, name) == 0)
7111 res->image = image->modules [i];
7114 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7115 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7116 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7117 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7118 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7124 verify_safe_for_managed_space (MonoType *type)
7126 switch (type->type) {
7128 case MONO_TYPE_ARRAY:
7129 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7131 return verify_safe_for_managed_space (type->data.type);
7132 case MONO_TYPE_SZARRAY:
7133 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7134 case MONO_TYPE_GENERICINST: {
7135 MonoGenericInst *inst = type->data.generic_class->inst;
7139 for (i = 0; i < inst->type_argc; ++i)
7140 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7146 case MONO_TYPE_MVAR:
7154 mono_type_normalize (MonoType *type)
7157 MonoGenericClass *gclass;
7158 MonoGenericInst *ginst;
7160 MonoGenericContainer *gcontainer;
7161 MonoType **argv = NULL;
7162 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7164 if (type->type != MONO_TYPE_GENERICINST)
7167 gclass = type->data.generic_class;
7168 ginst = gclass->context.class_inst;
7169 if (!ginst->is_open)
7172 gtd = gclass->container_class;
7173 gcontainer = gtd->generic_container;
7174 argv = g_newa (MonoType*, ginst->type_argc);
7176 for (i = 0; i < ginst->type_argc; ++i) {
7177 MonoType *t = ginst->type_argv [i], *norm;
7178 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7179 is_denorm_gtd = FALSE;
7180 norm = mono_type_normalize (t);
7183 requires_rebind = TRUE;
7187 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7189 if (requires_rebind) {
7190 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7191 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7197 * mono_type_get_object:
7198 * @domain: an app domain
7201 * Return an System.MonoType object representing the type @type.
7204 mono_type_get_object (MonoDomain *domain, MonoType *type)
7207 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7208 mono_error_cleanup (&error);
7214 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7216 MonoType *norm_type;
7217 MonoReflectionType *res;
7220 mono_error_init (error);
7222 klass = mono_class_from_mono_type (type);
7224 /*we must avoid using @type as it might have come
7225 * from a mono_metadata_type_dup and the caller
7226 * expects that is can be freed.
7227 * Using the right type from
7229 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7231 /* void is very common */
7232 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7233 return (MonoReflectionType*)domain->typeof_void;
7236 * If the vtable of the given class was already created, we can use
7237 * the MonoType from there and avoid all locking and hash table lookups.
7239 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7240 * that the resulting object is different.
7242 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7243 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7244 if (vtable && vtable->type)
7245 return (MonoReflectionType *)vtable->type;
7248 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7249 mono_domain_lock (domain);
7250 if (!domain->type_hash)
7251 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7252 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7253 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7254 mono_domain_unlock (domain);
7255 mono_loader_unlock ();
7259 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7260 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7261 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7262 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7263 * artifact of how generics are encoded and should be transparent to managed code so we
7264 * need to weed out this diference when retrieving managed System.Type objects.
7266 norm_type = mono_type_normalize (type);
7267 if (norm_type != type) {
7268 res = mono_type_get_object_checked (domain, norm_type, error);
7269 if (!mono_error_ok (error))
7271 mono_g_hash_table_insert (domain->type_hash, type, res);
7272 mono_domain_unlock (domain);
7273 mono_loader_unlock ();
7277 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7278 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7281 if (!verify_safe_for_managed_space (type)) {
7282 mono_domain_unlock (domain);
7283 mono_loader_unlock ();
7284 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7288 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7289 gboolean is_type_done = TRUE;
7290 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7291 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7292 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7294 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7295 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7297 if (gparam->owner && gparam->owner->is_method) {
7298 MonoMethod *method = gparam->owner->owner.method;
7299 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7300 is_type_done = FALSE;
7301 } else if (gparam->owner && !gparam->owner->is_method) {
7302 MonoClass *klass = gparam->owner->owner.klass;
7303 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7304 is_type_done = FALSE;
7308 /* g_assert_not_reached (); */
7309 /* should this be considered an error condition? */
7310 if (is_type_done && !type->byref) {
7311 mono_domain_unlock (domain);
7312 mono_loader_unlock ();
7313 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7316 /* This is stored in vtables/JITted code so it has to be pinned */
7317 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7318 if (!mono_error_ok (error))
7322 mono_g_hash_table_insert (domain->type_hash, type, res);
7324 if (type->type == MONO_TYPE_VOID)
7325 domain->typeof_void = (MonoObject*)res;
7327 mono_domain_unlock (domain);
7328 mono_loader_unlock ();
7333 * mono_method_get_object:
7334 * @domain: an app domain
7336 * @refclass: the reflected type (can be NULL)
7338 * Return an System.Reflection.MonoMethod object representing the method @method.
7340 MonoReflectionMethod*
7341 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7344 MonoReflectionMethod *ret = NULL;
7345 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7346 mono_error_cleanup (&error);
7351 * mono_method_get_object_checked:
7352 * @domain: an app domain
7354 * @refclass: the reflected type (can be NULL)
7355 * @error: set on error.
7357 * Return an System.Reflection.MonoMethod object representing the method @method.
7358 * Returns NULL and sets @error on error.
7360 MonoReflectionMethod*
7361 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7364 * We use the same C representation for methods and constructors, but the type
7365 * name in C# is different.
7367 MonoReflectionType *rt;
7369 MonoReflectionMethod *ret;
7371 mono_error_init (error);
7373 if (method->is_inflated) {
7374 MonoReflectionGenericMethod *gret;
7377 refclass = method->klass;
7378 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7379 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7380 klass = mono_class_get_mono_generic_cmethod_class ();
7382 klass = mono_class_get_mono_generic_method_class ();
7384 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7385 if (!mono_error_ok (error))
7387 gret->method.method = method;
7389 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7391 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7392 if (!mono_error_ok (error))
7395 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7397 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7401 refclass = method->klass;
7403 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7404 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7405 klass = mono_class_get_mono_cmethod_class ();
7408 klass = mono_class_get_mono_method_class ();
7410 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7411 if (!mono_error_ok (error))
7413 ret->method = method;
7415 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7416 if (!mono_error_ok (error))
7419 MONO_OBJECT_SETREF (ret, reftype, rt);
7421 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7424 g_assert (!mono_error_ok (error));
7429 * mono_method_clear_object:
7431 * Clear the cached reflection objects for the dynamic method METHOD.
7434 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7437 g_assert (method_is_dynamic (method));
7439 klass = method->klass;
7441 clear_cached_object (domain, method, klass);
7442 klass = klass->parent;
7444 /* Added by mono_param_get_objects () */
7445 clear_cached_object (domain, &(method->signature), NULL);
7446 klass = method->klass;
7448 clear_cached_object (domain, &(method->signature), klass);
7449 klass = klass->parent;
7454 * mono_field_get_object:
7455 * @domain: an app domain
7459 * Return an System.Reflection.MonoField object representing the field @field
7462 MonoReflectionField*
7463 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7466 MonoReflectionField *result;
7467 result = mono_field_get_object_checked (domain, klass, field, &error);
7468 mono_error_cleanup (&error);
7473 * mono_field_get_object_checked:
7474 * @domain: an app domain
7477 * @error: set on error
7479 * Return an System.Reflection.MonoField object representing the field @field
7480 * in class @klass. On error, returns NULL and sets @error.
7482 MonoReflectionField*
7483 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7485 MonoReflectionType *rt;
7486 MonoReflectionField *res;
7488 mono_error_init (error);
7490 CHECK_OBJECT (MonoReflectionField *, field, klass);
7491 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7496 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7498 if (is_field_on_inst (field)) {
7499 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7501 rt = mono_type_get_object_checked (domain, field->type, error);
7502 if (!mono_error_ok (error))
7505 MONO_OBJECT_SETREF (res, type, rt);
7508 rt = mono_type_get_object_checked (domain, field->type, error);
7509 if (!mono_error_ok (error))
7512 MONO_OBJECT_SETREF (res, type, rt);
7514 res->attrs = mono_field_get_flags (field);
7516 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7520 * mono_property_get_object:
7521 * @domain: an app domain
7523 * @property: a property
7525 * Return an System.Reflection.MonoProperty object representing the property @property
7528 MonoReflectionProperty*
7529 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7532 MonoReflectionProperty *result;
7533 result = mono_property_get_object_checked (domain, klass, property, &error);
7534 mono_error_cleanup (&error);
7539 * mono_property_get_object:
7540 * @domain: an app domain
7542 * @property: a property
7543 * @error: set on error
7545 * Return an System.Reflection.MonoProperty object representing the property @property
7546 * in class @klass. On error returns NULL and sets @error.
7548 MonoReflectionProperty*
7549 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7551 MonoReflectionProperty *res;
7553 mono_error_init (error);
7555 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7556 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7560 res->property = property;
7561 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7565 * mono_event_get_object:
7566 * @domain: an app domain
7570 * Return an System.Reflection.MonoEvent object representing the event @event
7573 MonoReflectionEvent*
7574 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7577 MonoReflectionEvent *result;
7578 result = mono_event_get_object_checked (domain, klass, event, &error);
7579 mono_error_cleanup (&error);
7584 * mono_event_get_object_checked:
7585 * @domain: an app domain
7588 * @error: set on error
7590 * Return an System.Reflection.MonoEvent object representing the event @event
7591 * in class @klass. On failure sets @error and returns NULL
7593 MonoReflectionEvent*
7594 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7596 MonoReflectionEvent *res;
7597 MonoReflectionMonoEvent *mono_event;
7599 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7600 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7603 mono_event->klass = klass;
7604 mono_event->event = event;
7605 res = (MonoReflectionEvent*)mono_event;
7606 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7610 * mono_get_reflection_missing_object:
7611 * @domain: Domain where the object lives
7613 * Returns the System.Reflection.Missing.Value singleton object
7614 * (of type System.Reflection.Missing).
7616 * Used as the value for ParameterInfo.DefaultValue when Optional
7620 mono_get_reflection_missing_object (MonoDomain *domain)
7624 static MonoClassField *missing_value_field = NULL;
7626 if (!missing_value_field) {
7627 MonoClass *missing_klass;
7628 missing_klass = mono_class_get_missing_class ();
7629 mono_class_init (missing_klass);
7630 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7631 g_assert (missing_value_field);
7633 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7634 mono_error_assert_ok (&error);
7639 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7642 *dbnull = mono_get_dbnull_object (domain);
7647 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7649 if (!*reflection_missing)
7650 *reflection_missing = mono_get_reflection_missing_object (domain);
7651 return *reflection_missing;
7655 * mono_param_get_objects:
7656 * @domain: an app domain
7659 * Return an System.Reflection.ParameterInfo array object representing the parameters
7660 * in the method @method.
7663 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7665 static MonoClass *System_Reflection_ParameterInfo;
7666 static MonoClass *System_Reflection_ParameterInfo_array;
7667 MonoArray *res = NULL;
7668 MonoReflectionMethod *member = NULL;
7669 MonoReflectionParameter *param = NULL;
7670 char **names = NULL, **blobs = NULL;
7671 guint32 *types = NULL;
7672 MonoType *type = NULL;
7673 MonoObject *dbnull = NULL;
7674 MonoObject *missing = NULL;
7675 MonoMarshalSpec **mspecs = NULL;
7676 MonoMethodSignature *sig = NULL;
7677 MonoVTable *pinfo_vtable;
7678 MonoReflectionType *rt;
7681 mono_error_init (error);
7683 if (!System_Reflection_ParameterInfo_array) {
7686 klass = mono_class_get_mono_parameter_info_class ();
7688 mono_memory_barrier ();
7689 System_Reflection_ParameterInfo = klass;
7692 klass = mono_array_class_get (klass, 1);
7693 mono_memory_barrier ();
7694 System_Reflection_ParameterInfo_array = klass;
7697 sig = mono_method_signature_checked (method, error);
7698 if (!mono_error_ok (error))
7701 if (!sig->param_count) {
7702 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7709 /* Note: the cache is based on the address of the signature into the method
7710 * since we already cache MethodInfos with the method as keys.
7712 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7714 member = mono_method_get_object_checked (domain, method, refclass, error);
7717 names = g_new (char *, sig->param_count);
7718 mono_method_get_param_names (method, (const char **) names);
7720 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7721 mono_method_get_marshal_info (method, mspecs);
7723 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7727 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7728 for (i = 0; i < sig->param_count; ++i) {
7729 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7733 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7737 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7739 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7741 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7743 param->PositionImpl = i;
7744 param->AttrsImpl = sig->params [i]->attrs;
7746 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7747 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7748 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7750 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7754 blobs = g_new0 (char *, sig->param_count);
7755 types = g_new0 (guint32, sig->param_count);
7756 get_default_param_value_blobs (method, blobs, types);
7759 /* Build MonoType for the type from the Constant Table */
7761 type = g_new0 (MonoType, 1);
7762 type->type = (MonoTypeEnum)types [i];
7763 type->data.klass = NULL;
7764 if (types [i] == MONO_TYPE_CLASS)
7765 type->data.klass = mono_defaults.object_class;
7766 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7767 /* For enums, types [i] contains the base type */
7769 type->type = MONO_TYPE_VALUETYPE;
7770 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7772 type->data.klass = mono_class_from_mono_type (type);
7774 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7777 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7779 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7780 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7781 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7782 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7784 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7789 if (mspecs [i + 1]) {
7790 MonoReflectionMarshalAsAttribute* mobj;
7791 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7794 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7797 mono_array_setref (res, i, param);
7807 for (i = sig->param_count; i >= 0; i--) {
7809 mono_metadata_free_marshal_spec (mspecs [i]);
7817 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7821 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7824 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7825 mono_error_assert_ok (&error);
7830 * mono_method_body_get_object:
7831 * @domain: an app domain
7834 * Return an System.Reflection.MethodBody object representing the method @method.
7836 MonoReflectionMethodBody*
7837 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7840 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7841 mono_error_cleanup (&error);
7846 * mono_method_body_get_object_checked:
7847 * @domain: an app domain
7849 * @error: set on error
7851 * Return an System.Reflection.MethodBody object representing the
7852 * method @method. On failure, returns NULL and sets @error.
7854 MonoReflectionMethodBody*
7855 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7857 MonoReflectionMethodBody *ret;
7858 MonoMethodHeader *header;
7860 MonoReflectionType *rt;
7861 guint32 method_rva, local_var_sig_token;
7863 unsigned char format, flags;
7866 mono_error_init (error);
7868 /* for compatibility with .net */
7869 if (method_is_dynamic (method)) {
7870 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7874 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7876 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7877 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7878 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7879 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7880 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7883 image = method->klass->image;
7884 header = mono_method_get_header_checked (method, error);
7885 return_val_if_nok (error, NULL);
7887 if (!image_is_dynamic (image)) {
7888 /* Obtain local vars signature token */
7889 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7890 ptr = mono_image_rva_map (image, method_rva);
7891 flags = *(const unsigned char *) ptr;
7892 format = flags & METHOD_HEADER_FORMAT_MASK;
7894 case METHOD_HEADER_TINY_FORMAT:
7895 local_var_sig_token = 0;
7897 case METHOD_HEADER_FAT_FORMAT:
7901 local_var_sig_token = read32 (ptr);
7904 g_assert_not_reached ();
7907 local_var_sig_token = 0; //FIXME
7909 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7913 ret->init_locals = header->init_locals;
7914 ret->max_stack = header->max_stack;
7915 ret->local_var_sig_token = local_var_sig_token;
7916 MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7919 MONO_OBJECT_SETREF (ret, il, il_arr);
7920 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7923 MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7926 MONO_OBJECT_SETREF (ret, locals, locals_arr);
7927 for (i = 0; i < header->num_locals; ++i) {
7928 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7932 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7936 MONO_OBJECT_SETREF (info, local_type, rt);
7938 info->is_pinned = header->locals [i]->pinned;
7939 info->local_index = i;
7940 mono_array_setref (ret->locals, i, info);
7944 MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7947 MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7948 for (i = 0; i < header->num_clauses; ++i) {
7949 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7952 MonoExceptionClause *clause = &header->clauses [i];
7954 info->flags = clause->flags;
7955 info->try_offset = clause->try_offset;
7956 info->try_length = clause->try_len;
7957 info->handler_offset = clause->handler_offset;
7958 info->handler_length = clause->handler_len;
7959 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7960 info->filter_offset = clause->data.filter_offset;
7961 else if (clause->data.catch_class) {
7962 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7966 MONO_OBJECT_SETREF (info, catch_type, rt);
7969 mono_array_setref (ret->clauses, i, info);
7972 mono_metadata_free_mh (header);
7973 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7977 mono_metadata_free_mh (header);
7982 * mono_get_dbnull_object:
7983 * @domain: Domain where the object lives
7985 * Returns the System.DBNull.Value singleton object
7987 * Used as the value for ParameterInfo.DefaultValue
7990 mono_get_dbnull_object (MonoDomain *domain)
7994 static MonoClassField *dbnull_value_field = NULL;
7996 if (!dbnull_value_field) {
7997 MonoClass *dbnull_klass;
7998 dbnull_klass = mono_class_get_dbnull_class ();
7999 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8000 g_assert (dbnull_value_field);
8002 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8003 mono_error_assert_ok (&error);
8008 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8010 guint32 param_index, i, lastp, crow = 0;
8011 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8014 MonoClass *klass = method->klass;
8015 MonoImage *image = klass->image;
8016 MonoMethodSignature *methodsig = mono_method_signature (method);
8018 MonoTableInfo *constt;
8019 MonoTableInfo *methodt;
8020 MonoTableInfo *paramt;
8022 if (!methodsig->param_count)
8025 mono_class_init (klass);
8027 if (image_is_dynamic (klass->image)) {
8028 MonoReflectionMethodAux *aux;
8029 if (method->is_inflated)
8030 method = ((MonoMethodInflated*)method)->declaring;
8031 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8032 if (aux && aux->param_defaults) {
8033 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8034 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8039 methodt = &klass->image->tables [MONO_TABLE_METHOD];
8040 paramt = &klass->image->tables [MONO_TABLE_PARAM];
8041 constt = &image->tables [MONO_TABLE_CONSTANT];
8043 idx = mono_method_get_index (method) - 1;
8044 g_assert (idx != -1);
8046 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8047 if (idx + 1 < methodt->rows)
8048 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8050 lastp = paramt->rows + 1;
8052 for (i = param_index; i < lastp; ++i) {
8055 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8056 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8058 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8061 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8066 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8067 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8068 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8075 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8080 MonoType *basetype = type;
8082 mono_error_init (error);
8087 klass = mono_class_from_mono_type (type);
8088 if (klass->valuetype) {
8089 object = mono_object_new_checked (domain, klass, error);
8090 return_val_if_nok (error, NULL);
8091 retval = ((gchar *) object + sizeof (MonoObject));
8092 if (klass->enumtype)
8093 basetype = mono_class_enum_basetype (klass);
8098 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
8105 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8108 gboolean quoted = FALSE;
8110 memset (assembly, 0, sizeof (MonoAssemblyName));
8111 assembly->culture = "";
8112 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8119 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8130 /* Remove trailing whitespace */
8132 while (*s && g_ascii_isspace (*s))
8135 while (g_ascii_isspace (*p))
8138 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8140 assembly->major = strtoul (p, &s, 10);
8141 if (s == p || *s != '.')
8144 assembly->minor = strtoul (p, &s, 10);
8145 if (s == p || *s != '.')
8148 assembly->build = strtoul (p, &s, 10);
8149 if (s == p || *s != '.')
8152 assembly->revision = strtoul (p, &s, 10);
8156 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8158 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8159 assembly->culture = "";
8162 assembly->culture = p;
8163 while (*p && *p != ',') {
8167 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8169 if (strncmp (p, "null", 4) == 0) {
8174 while (*p && *p != ',') {
8177 len = (p - start + 1);
8178 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8179 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8180 g_strlcpy ((char*)assembly->public_key_token, start, len);
8183 while (*p && *p != ',')
8187 while (g_ascii_isspace (*p) || *p == ',') {
8201 * mono_reflection_parse_type:
8204 * Parse a type name as accepted by the GetType () method and output the info
8205 * extracted in the info structure.
8206 * the name param will be mangled, so, make a copy before passing it to this function.
8207 * The fields in info will be valid until the memory pointed to by name is valid.
8209 * See also mono_type_get_name () below.
8211 * Returns: 0 on parse error.
8214 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8215 MonoTypeNameParse *info)
8217 char *start, *p, *w, *last_point, *startn;
8218 int in_modifiers = 0;
8219 int isbyref = 0, rank = 0, isptr = 0;
8221 start = p = w = name;
8223 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8224 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8225 info->name = info->name_space = NULL;
8226 info->nested = NULL;
8227 info->modifiers = NULL;
8228 info->type_arguments = NULL;
8230 /* last_point separates the namespace from the name */
8233 while (*p == ' ') p++, start++, w++, name++;
8238 *p = 0; /* NULL terminate the name */
8240 info->nested = g_list_append (info->nested, startn);
8241 /* we have parsed the nesting namespace + name */
8245 info->name_space = start;
8247 info->name = last_point + 1;
8249 info->name_space = (char *)"";
8277 info->name_space = start;
8279 info->name = last_point + 1;
8281 info->name_space = (char *)"";
8288 if (isbyref) /* only one level allowed by the spec */
8292 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8296 if (isbyref) /* pointer to ref not okay */
8298 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8303 if (isbyref) /* array of ref and generic ref are not okay */
8305 //Decide if it's an array of a generic argument list
8310 if (*p == ',' || *p == '*' || *p == ']') { //array
8318 else if (*p == '*') /* '*' means unknown lower bound */
8319 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8326 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8328 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8331 info->type_arguments = g_ptr_array_new ();
8333 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8334 gboolean fqname = FALSE;
8336 g_ptr_array_add (info->type_arguments, subinfo);
8338 while (*p == ' ') p++;
8344 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8347 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8348 if (fqname && (*p != ']')) {
8356 while (*p && (*p != ']'))
8364 if (g_ascii_isspace (*aname)) {
8371 !assembly_name_to_aname (&subinfo->assembly, aname))
8373 } else if (fqname && (*p == ']')) {
8395 if (g_ascii_isspace (*p)) {
8402 return 0; /* missing assembly name */
8403 if (!assembly_name_to_aname (&info->assembly, p))
8409 if (info->assembly.name)
8412 // *w = 0; /* terminate class name */
8414 if (!info->name || !*info->name)
8418 /* add other consistency checks */
8424 * mono_identifier_unescape_type_name_chars:
8425 * @identifier: the display name of a mono type
8428 * The name in internal form, that is without escaping backslashes.
8430 * The string is modified in place!
8433 mono_identifier_unescape_type_name_chars(char* identifier)
8438 for (w = r = identifier; *r != 0; r++)
8456 mono_identifier_unescape_info (MonoTypeNameParse* info);
8459 unescape_each_type_argument(void* data, void* user_data)
8461 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8462 mono_identifier_unescape_info (info);
8466 unescape_each_nested_name (void* data, void* user_data)
8468 char* nested_name = (char*) data;
8469 mono_identifier_unescape_type_name_chars(nested_name);
8473 * mono_identifier_unescape_info:
8475 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8479 * Destructively updates the info by unescaping the identifiers that
8480 * comprise the type namespace, name, nested types (if any) and
8481 * generic type arguments (if any).
8483 * The resulting info has the names in internal form.
8487 mono_identifier_unescape_info (MonoTypeNameParse *info)
8491 mono_identifier_unescape_type_name_chars(info->name_space);
8492 mono_identifier_unescape_type_name_chars(info->name);
8493 // but don't escape info->assembly
8494 if (info->type_arguments)
8495 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8497 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8501 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8503 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8505 mono_identifier_unescape_info (info);
8511 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8513 gboolean type_resolve = FALSE;
8515 MonoImage *rootimage = image;
8517 mono_error_init (error);
8519 if (info->assembly.name) {
8520 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8521 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8523 * This could happen in the AOT compiler case when the search hook is not
8526 assembly = image->assembly;
8528 /* then we must load the assembly ourselve - see #60439 */
8529 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8533 image = assembly->image;
8534 } else if (!image) {
8535 image = mono_defaults.corlib;
8538 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8539 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8540 /* ignore the error and try again */
8541 mono_error_cleanup (error);
8542 mono_error_init (error);
8543 image = mono_defaults.corlib;
8544 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8551 * mono_reflection_get_type_internal:
8553 * Returns: may return NULL on success, sets error on failure.
8556 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8561 gboolean bounded = FALSE;
8563 mono_error_init (error);
8565 image = mono_defaults.corlib;
8568 rootimage = mono_defaults.corlib;
8571 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8573 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8578 for (mod = info->nested; mod; mod = mod->next) {
8579 gpointer iter = NULL;
8583 mono_class_init (parent);
8585 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8587 char *nested_name, *nested_nspace;
8588 gboolean match = TRUE;
8590 lastp = strrchr ((const char *)mod->data, '.');
8592 /* Nested classes can have namespaces */
8595 nested_name = g_strdup (lastp + 1);
8596 nspace_len = lastp - (char*)mod->data;
8597 nested_nspace = (char *)g_malloc (nspace_len + 1);
8598 memcpy (nested_nspace, mod->data, nspace_len);
8599 nested_nspace [nspace_len] = '\0';
8602 nested_name = (char *)mod->data;
8603 nested_nspace = NULL;
8606 if (nested_nspace) {
8608 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8611 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8617 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8620 if (strcmp (klass->name, nested_name) != 0)
8625 g_free (nested_name);
8626 g_free (nested_nspace);
8638 if (info->type_arguments) {
8639 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8640 MonoReflectionType *the_type;
8644 for (i = 0; i < info->type_arguments->len; i++) {
8645 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8647 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8648 if (!type_args [i]) {
8654 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8658 instance = mono_reflection_bind_generic_parameters (
8659 the_type, info->type_arguments->len, type_args, error);
8665 klass = mono_class_from_mono_type (instance);
8668 for (mod = info->modifiers; mod; mod = mod->next) {
8669 modval = GPOINTER_TO_UINT (mod->data);
8670 if (!modval) { /* byref: must be last modifier */
8671 return &klass->this_arg;
8672 } else if (modval == -1) {
8673 klass = mono_ptr_class_get (&klass->byval_arg);
8674 } else if (modval == -2) {
8676 } else { /* array rank */
8677 klass = mono_bounded_array_class_get (klass, modval, bounded);
8681 return &klass->byval_arg;
8685 * mono_reflection_get_type:
8686 * @image: a metadata context
8687 * @info: type description structure
8688 * @ignorecase: flag for case-insensitive string compares
8689 * @type_resolve: whenever type resolve was already tried
8691 * Build a MonoType from the type description in @info.
8696 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8698 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8699 mono_error_cleanup (&error);
8704 * mono_reflection_get_type_checked:
8705 * @rootimage: the image of the currently active managed caller
8706 * @image: a metadata context
8707 * @info: type description structure
8708 * @ignorecase: flag for case-insensitive string compares
8709 * @type_resolve: whenever type resolve was already tried
8710 * @error: set on error.
8712 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8716 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8717 mono_error_init (error);
8718 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8723 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8725 MonoReflectionAssemblyBuilder *abuilder;
8729 mono_error_init (error);
8730 g_assert (assembly_is_dynamic (assembly));
8731 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8735 /* Enumerate all modules */
8738 if (abuilder->modules) {
8739 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8740 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8741 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8744 if (!mono_error_ok (error))
8749 if (!type && abuilder->loaded_modules) {
8750 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8751 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8752 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8755 if (!mono_error_ok (error))
8764 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8767 MonoReflectionAssembly *assembly;
8771 mono_error_init (error);
8773 if (image && image_is_dynamic (image))
8774 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8776 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8778 return_val_if_nok (error, NULL);
8782 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8789 *type_resolve = TRUE;
8792 /* Reconstruct the type name */
8793 fullName = g_string_new ("");
8794 if (info->name_space && (info->name_space [0] != '\0'))
8795 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8797 g_string_printf (fullName, "%s", info->name);
8798 for (mod = info->nested; mod; mod = mod->next)
8799 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8801 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8802 if (!is_ok (error)) {
8803 g_string_free (fullName, TRUE);
8808 if (assembly_is_dynamic (assembly->assembly))
8809 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8810 info, ignorecase, error);
8812 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8813 info, ignorecase, error);
8815 g_string_free (fullName, TRUE);
8816 return_val_if_nok (error, NULL);
8821 mono_reflection_free_type_info (MonoTypeNameParse *info)
8823 g_list_free (info->modifiers);
8824 g_list_free (info->nested);
8826 if (info->type_arguments) {
8829 for (i = 0; i < info->type_arguments->len; i++) {
8830 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8832 mono_reflection_free_type_info (subinfo);
8833 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8837 g_ptr_array_free (info->type_arguments, TRUE);
8842 * mono_reflection_type_from_name:
8844 * @image: a metadata context (can be NULL).
8846 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8847 * it defaults to get the type from @image or, if @image is NULL or loading
8848 * from it fails, uses corlib.
8852 mono_reflection_type_from_name (char *name, MonoImage *image)
8855 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8856 mono_error_cleanup (&error);
8861 * mono_reflection_type_from_name_checked:
8863 * @image: a metadata context (can be NULL).
8864 * @error: set on errror.
8866 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8867 * it defaults to get the type from @image or, if @image is NULL or loading
8868 * from it fails, uses corlib. On failure returns NULL and sets @error.
8872 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8874 MonoType *type = NULL;
8875 MonoTypeNameParse info;
8878 mono_error_init (error);
8879 /* Make a copy since parse_type modifies its argument */
8880 tmp = g_strdup (name);
8882 /*g_print ("requested type %s\n", str);*/
8883 if (mono_reflection_parse_type (tmp, &info)) {
8884 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8885 if (!is_ok (error)) {
8887 mono_reflection_free_type_info (&info);
8893 mono_reflection_free_type_info (&info);
8898 * mono_reflection_get_token:
8900 * Return the metadata token of OBJ which should be an object
8901 * representing a metadata element.
8904 mono_reflection_get_token (MonoObject *obj)
8907 guint32 result = mono_reflection_get_token_checked (obj, &error);
8908 mono_error_assert_ok (&error);
8913 * mono_reflection_get_token_checked:
8915 * @error: set on error
8917 * Return the metadata token of @obj which should be an object
8918 * representing a metadata element. On failure sets @error.
8921 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8926 mono_error_init (error);
8928 klass = obj->vtable->klass;
8930 if (strcmp (klass->name, "MethodBuilder") == 0) {
8931 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8933 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8934 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8935 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8937 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8938 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8939 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8941 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8942 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8943 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8944 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8945 } else if (strcmp (klass->name, "RuntimeType") == 0) {
8946 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8947 return_val_if_nok (error, 0);
8948 MonoClass *mc = mono_class_from_mono_type (type);
8949 if (!mono_class_init (mc)) {
8950 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8954 token = mc->type_token;
8955 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8956 strcmp (klass->name, "MonoMethod") == 0 ||
8957 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8958 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8959 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8960 if (m->method->is_inflated) {
8961 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8962 return inflated->declaring->token;
8964 token = m->method->token;
8966 } else if (strcmp (klass->name, "MonoField") == 0) {
8967 MonoReflectionField *f = (MonoReflectionField*)obj;
8969 if (is_field_on_inst (f->field)) {
8970 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8972 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8973 int field_index = f->field - dgclass->fields;
8976 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8977 obj = dgclass->field_objects [field_index];
8978 return mono_reflection_get_token_checked (obj, error);
8981 token = mono_class_get_field_token (f->field);
8982 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8983 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8985 token = mono_class_get_property_token (p->property);
8986 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8987 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8989 token = mono_class_get_event_token (p->event);
8990 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8991 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8992 MonoClass *member_class = mono_object_class (p->MemberImpl);
8993 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8995 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8996 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8997 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9000 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9001 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9003 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9004 klass->name_space, klass->name);
9012 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
9013 * The @is_enum flag only affects the error message that's displayed on failure.
9016 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9018 MonoError inner_error;
9019 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9021 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9022 "Could not load %s %s while decoding custom attribute: %s",
9023 is_enum ? "enum type": "type",
9025 mono_error_get_message (&inner_error));
9026 mono_error_cleanup (&inner_error);
9033 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9037 int slen = mono_metadata_decode_value (p, &p);
9039 mono_error_init (error);
9041 n = (char *)g_memdup (p, slen + 1);
9043 t = cattr_type_from_name (n, image, TRUE, error);
9045 return_val_if_nok (error, NULL);
9048 return mono_class_from_mono_type (t);
9052 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9054 int slen, type = t->type;
9055 MonoClass *tklass = t->data.klass;
9057 mono_error_init (error);
9063 case MONO_TYPE_BOOLEAN: {
9064 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9069 case MONO_TYPE_CHAR:
9071 case MONO_TYPE_I2: {
9072 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9077 #if SIZEOF_VOID_P == 4
9083 case MONO_TYPE_I4: {
9084 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9089 #if SIZEOF_VOID_P == 8
9090 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9094 case MONO_TYPE_I8: {
9095 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9100 case MONO_TYPE_R8: {
9101 double *val = (double *)g_malloc (sizeof (double));
9106 case MONO_TYPE_VALUETYPE:
9107 if (t->data.klass->enumtype) {
9108 type = mono_class_enum_basetype (t->data.klass)->type;
9111 MonoClass *k = t->data.klass;
9113 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9114 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9120 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9123 case MONO_TYPE_STRING:
9124 if (*p == (char)0xFF) {
9128 slen = mono_metadata_decode_value (p, &p);
9130 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9131 case MONO_TYPE_CLASS: {
9132 MonoReflectionType *rt;
9135 if (*p == (char)0xFF) {
9140 slen = mono_metadata_decode_value (p, &p);
9141 n = (char *)g_memdup (p, slen + 1);
9143 t = cattr_type_from_name (n, image, FALSE, error);
9145 return_val_if_nok (error, NULL);
9148 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9149 if (!mono_error_ok (error))
9154 case MONO_TYPE_OBJECT: {
9157 MonoClass *subc = NULL;
9162 } else if (subt == 0x0E) {
9163 type = MONO_TYPE_STRING;
9165 } else if (subt == 0x1D) {
9166 MonoType simple_type = {{0}};
9170 type = MONO_TYPE_SZARRAY;
9171 if (etype == 0x50) {
9172 tklass = mono_defaults.systemtype_class;
9173 } else if (etype == 0x55) {
9174 tklass = load_cattr_enum_type (image, p, &p, error);
9175 if (!mono_error_ok (error))
9179 /* See Partition II, Appendix B3 */
9180 etype = MONO_TYPE_OBJECT;
9181 simple_type.type = (MonoTypeEnum)etype;
9182 tklass = mono_class_from_mono_type (&simple_type);
9185 } else if (subt == 0x55) {
9188 slen = mono_metadata_decode_value (p, &p);
9189 n = (char *)g_memdup (p, slen + 1);
9191 t = cattr_type_from_name (n, image, FALSE, error);
9193 return_val_if_nok (error, NULL);
9195 subc = mono_class_from_mono_type (t);
9196 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9197 MonoType simple_type = {{0}};
9198 simple_type.type = (MonoTypeEnum)subt;
9199 subc = mono_class_from_mono_type (&simple_type);
9201 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9203 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9205 if (mono_error_ok (error)) {
9206 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9207 g_assert (!subc->has_references);
9208 if (mono_error_ok (error))
9209 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9215 case MONO_TYPE_SZARRAY: {
9217 guint32 i, alen, basetype;
9220 if (alen == 0xffffffff) {
9224 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9225 return_val_if_nok (error, NULL);
9226 basetype = tklass->byval_arg.type;
9227 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9228 basetype = mono_class_enum_basetype (tklass)->type;
9233 case MONO_TYPE_BOOLEAN:
9234 for (i = 0; i < alen; i++) {
9235 MonoBoolean val = *p++;
9236 mono_array_set (arr, MonoBoolean, i, val);
9239 case MONO_TYPE_CHAR:
9242 for (i = 0; i < alen; i++) {
9243 guint16 val = read16 (p);
9244 mono_array_set (arr, guint16, i, val);
9251 for (i = 0; i < alen; i++) {
9252 guint32 val = read32 (p);
9253 mono_array_set (arr, guint32, i, val);
9258 for (i = 0; i < alen; i++) {
9261 mono_array_set (arr, double, i, val);
9267 for (i = 0; i < alen; i++) {
9268 guint64 val = read64 (p);
9269 mono_array_set (arr, guint64, i, val);
9273 case MONO_TYPE_CLASS:
9274 case MONO_TYPE_OBJECT:
9275 case MONO_TYPE_STRING:
9276 case MONO_TYPE_SZARRAY:
9277 for (i = 0; i < alen; i++) {
9278 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9279 if (!mono_error_ok (error))
9281 mono_array_setref (arr, i, item);
9285 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9291 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9297 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9299 mono_error_init (error);
9301 gboolean is_ref = type_is_reference (t);
9303 void *val = load_cattr_value (image, t, p, end, error);
9304 if (!is_ok (error)) {
9311 return (MonoObject*)val;
9313 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9319 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9321 static MonoMethod *ctor;
9323 void *params [2], *unboxed;
9325 mono_error_init (error);
9328 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9330 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9331 return_val_if_nok (error, NULL);
9334 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9335 return_val_if_nok (error, NULL);
9336 unboxed = mono_object_unbox (retval);
9338 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9339 return_val_if_nok (error, NULL);
9345 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9347 static MonoMethod *ctor;
9349 void *unboxed, *params [2];
9351 mono_error_init (error);
9354 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9357 params [1] = typedarg;
9358 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9359 return_val_if_nok (error, NULL);
9361 unboxed = mono_object_unbox (retval);
9363 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9364 return_val_if_nok (error, NULL);
9370 type_is_reference (MonoType *type)
9372 switch (type->type) {
9373 case MONO_TYPE_BOOLEAN:
9374 case MONO_TYPE_CHAR:
9387 case MONO_TYPE_VALUETYPE:
9395 free_param_data (MonoMethodSignature *sig, void **params) {
9397 for (i = 0; i < sig->param_count; ++i) {
9398 if (!type_is_reference (sig->params [i]))
9399 g_free (params [i]);
9404 * Find the field index in the metadata FieldDef table.
9407 find_field_index (MonoClass *klass, MonoClassField *field) {
9410 for (i = 0; i < klass->field.count; ++i) {
9411 if (field == &klass->fields [i])
9412 return klass->field.first + 1 + i;
9418 * Find the property index in the metadata Property table.
9421 find_property_index (MonoClass *klass, MonoProperty *property) {
9424 for (i = 0; i < klass->ext->property.count; ++i) {
9425 if (property == &klass->ext->properties [i])
9426 return klass->ext->property.first + 1 + i;
9432 * Find the event index in the metadata Event table.
9435 find_event_index (MonoClass *klass, MonoEvent *event) {
9438 for (i = 0; i < klass->ext->event.count; ++i) {
9439 if (event == &klass->ext->events [i])
9440 return klass->ext->event.first + 1 + i;
9446 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9448 const char *p = (const char*)data;
9450 guint32 i, j, num_named;
9452 void *params_buf [32];
9453 void **params = NULL;
9454 MonoMethodSignature *sig;
9456 mono_error_init (error);
9458 mono_class_init (method->klass);
9460 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9461 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9466 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9467 if (!mono_error_ok (error)) return NULL;
9469 mono_runtime_invoke_checked (method, attr, NULL, error);
9470 if (!mono_error_ok (error))
9476 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9479 /*g_print ("got attr %s\n", method->klass->name);*/
9481 sig = mono_method_signature (method);
9482 if (sig->param_count < 32) {
9483 params = params_buf;
9484 memset (params, 0, sizeof (void*) * sig->param_count);
9486 /* Allocate using GC so it gets GC tracking */
9487 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9492 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9493 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9494 if (!mono_error_ok (error))
9499 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9500 if (!mono_error_ok (error)) goto fail;
9502 MonoObject *exc = NULL;
9503 mono_runtime_try_invoke (method, attr, params, &exc, error);
9504 if (!mono_error_ok (error))
9507 mono_error_set_exception_instance (error, (MonoException*)exc);
9511 num_named = read16 (named);
9513 for (j = 0; j < num_named; j++) {
9515 char *name, named_type, data_type;
9516 named_type = *named++;
9517 data_type = *named++; /* type of data */
9518 if (data_type == MONO_TYPE_SZARRAY)
9519 data_type = *named++;
9520 if (data_type == MONO_TYPE_ENUM) {
9523 type_len = mono_metadata_decode_blob_size (named, &named);
9524 type_name = (char *)g_malloc (type_len + 1);
9525 memcpy (type_name, named, type_len);
9526 type_name [type_len] = 0;
9528 /* FIXME: lookup the type and check type consistency */
9531 name_len = mono_metadata_decode_blob_size (named, &named);
9532 name = (char *)g_malloc (name_len + 1);
9533 memcpy (name, named, name_len);
9534 name [name_len] = 0;
9536 if (named_type == 0x53) {
9537 MonoClassField *field;
9540 /* how this fail is a blackbox */
9541 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9543 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9548 val = load_cattr_value (image, field->type, named, &named, error);
9549 if (!mono_error_ok (error)) {
9551 if (!type_is_reference (field->type))
9556 mono_field_set_value (attr, field, val);
9557 if (!type_is_reference (field->type))
9559 } else if (named_type == 0x54) {
9562 MonoType *prop_type;
9564 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9567 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9573 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9578 /* can we have more that 1 arg in a custom attr named property? */
9579 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9580 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9582 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9583 if (!mono_error_ok (error)) {
9585 if (!type_is_reference (prop_type))
9586 g_free (pparams [0]);
9591 mono_property_set_value_checked (prop, attr, pparams, error);
9592 if (!type_is_reference (prop_type))
9593 g_free (pparams [0]);
9594 if (!is_ok (error)) {
9602 free_param_data (method->signature, params);
9603 if (params != params_buf)
9604 mono_gc_free_fixed (params);
9609 free_param_data (method->signature, params);
9610 if (params != params_buf)
9611 mono_gc_free_fixed (params);
9616 * mono_reflection_create_custom_attr_data_args:
9618 * Create an array of typed and named arguments from the cattr blob given by DATA.
9619 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9620 * NAMED_ARG_INFO will contain information about the named arguments.
9623 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)
9625 MonoArray *typedargs, *namedargs;
9626 MonoClass *attrklass;
9628 const char *p = (const char*)data;
9630 guint32 i, j, num_named;
9631 CattrNamedArg *arginfo = NULL;
9635 *named_arg_info = NULL;
9637 mono_error_init (error);
9639 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9640 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9644 mono_class_init (method->klass);
9646 domain = mono_domain_get ();
9648 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9651 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9652 return_if_nok (error);
9656 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9659 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9660 return_if_nok (error);
9661 mono_array_setref (typedargs, i, obj);
9665 num_named = read16 (named);
9666 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9667 return_if_nok (error);
9669 attrklass = method->klass;
9671 arginfo = g_new0 (CattrNamedArg, num_named);
9672 *named_arg_info = arginfo;
9674 for (j = 0; j < num_named; j++) {
9676 char *name, named_type, data_type;
9677 named_type = *named++;
9678 data_type = *named++; /* type of data */
9679 if (data_type == MONO_TYPE_SZARRAY)
9680 data_type = *named++;
9681 if (data_type == MONO_TYPE_ENUM) {
9684 type_len = mono_metadata_decode_blob_size (named, &named);
9685 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9688 type_name = (char *)g_malloc (type_len + 1);
9689 memcpy (type_name, named, type_len);
9690 type_name [type_len] = 0;
9692 /* FIXME: lookup the type and check type consistency */
9695 name_len = mono_metadata_decode_blob_size (named, &named);
9696 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9698 name = (char *)g_malloc (name_len + 1);
9699 memcpy (name, named, name_len);
9700 name [name_len] = 0;
9702 if (named_type == 0x53) {
9704 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9711 arginfo [j].type = field->type;
9712 arginfo [j].field = field;
9714 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9715 if (!is_ok (error)) {
9719 mono_array_setref (namedargs, j, obj);
9721 } else if (named_type == 0x54) {
9723 MonoType *prop_type;
9724 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9726 if (!prop || !prop->set) {
9731 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9732 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9734 arginfo [j].type = prop_type;
9735 arginfo [j].prop = prop;
9737 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9738 if (!is_ok (error)) {
9742 mono_array_setref (namedargs, j, obj);
9747 *typed_args = typedargs;
9748 *named_args = namedargs;
9751 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9753 *named_arg_info = NULL;
9757 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9760 MonoArray *typedargs, *namedargs;
9763 CattrNamedArg *arginfo = NULL;
9766 mono_error_init (error);
9774 image = assembly->assembly->image;
9775 method = ref_method->method;
9776 domain = mono_object_domain (ref_method);
9778 if (!mono_class_init (method->klass)) {
9779 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->klass));
9783 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9787 if (!typedargs || !namedargs)
9790 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9791 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9792 MonoObject *typedarg;
9794 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9797 mono_array_setref (typedargs, i, typedarg);
9800 for (i = 0; i < mono_array_length (namedargs); ++i) {
9801 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9802 MonoObject *typedarg, *namedarg, *minfo;
9804 if (arginfo [i].prop) {
9805 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9809 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9814 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9817 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9821 mono_array_setref (namedargs, i, namedarg);
9824 *ctor_args = typedargs;
9825 *named_args = namedargs;
9829 return mono_error_ok (error);
9833 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9836 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9837 mono_error_set_pending_exception (&error);
9841 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9843 static MonoMethod *ctor;
9849 mono_error_init (error);
9851 g_assert (image->assembly);
9854 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9856 domain = mono_domain_get ();
9857 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9858 return_val_if_nok (error, NULL);
9859 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9860 return_val_if_nok (error, NULL);
9861 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9862 return_val_if_nok (error, NULL);
9863 params [2] = (gpointer)&cattr->data;
9864 params [3] = &cattr->data_size;
9866 mono_runtime_invoke_checked (ctor, attr, params, error);
9867 return_val_if_nok (error, NULL);
9872 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9878 mono_error_init (error);
9881 for (i = 0; i < cinfo->num_attrs; ++i) {
9882 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9886 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9887 return_val_if_nok (error, NULL);
9889 for (i = 0; i < cinfo->num_attrs; ++i) {
9890 if (!cinfo->attrs [i].ctor) {
9891 /* The cattr type is not finished yet */
9892 /* We should include the type name but cinfo doesn't contain it */
9893 mono_error_set_type_load_name (error, NULL, NULL, "");
9896 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9897 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9898 if (!mono_error_ok (error))
9900 mono_array_setref (result, n, attr);
9908 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9911 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9912 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9918 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9924 mono_error_init (error);
9925 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9926 return_val_if_nok (error, NULL);
9927 for (i = 0; i < cinfo->num_attrs; ++i) {
9928 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9929 return_val_if_nok (error, NULL);
9930 mono_array_setref (result, i, attr);
9936 * mono_custom_attrs_from_index:
9938 * Returns: NULL if no attributes are found or if a loading error occurs.
9941 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9944 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9945 mono_error_cleanup (&error);
9949 * mono_custom_attrs_from_index_checked:
9951 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9954 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9956 guint32 mtoken, i, len;
9957 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9959 MonoCustomAttrInfo *ainfo;
9960 GList *tmp, *list = NULL;
9962 MonoCustomAttrEntry* attr;
9964 mono_error_init (error);
9966 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9968 i = mono_metadata_custom_attrs_from_index (image, idx);
9972 while (i < ca->rows) {
9973 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9975 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9978 len = g_list_length (list);
9981 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9982 ainfo->num_attrs = len;
9983 ainfo->image = image;
9984 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9985 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9986 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9987 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9988 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9989 mtoken |= MONO_TOKEN_METHOD_DEF;
9991 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9992 mtoken |= MONO_TOKEN_MEMBER_REF;
9995 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9998 attr = &ainfo->attrs [i - 1];
9999 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10001 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10002 g_list_free (list);
10007 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10008 /*FIXME raising an exception here doesn't make any sense*/
10009 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10010 g_list_free (list);
10014 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10015 attr->data_size = mono_metadata_decode_value (data, &data);
10016 attr->data = (guchar*)data;
10018 g_list_free (list);
10023 MonoCustomAttrInfo*
10024 mono_custom_attrs_from_method (MonoMethod *method)
10027 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
10028 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10032 MonoCustomAttrInfo*
10033 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10037 mono_error_init (error);
10040 * An instantiated method has the same cattrs as the generic method definition.
10042 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10043 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10045 if (method->is_inflated)
10046 method = ((MonoMethodInflated *) method)->declaring;
10048 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10049 return lookup_custom_attr (method->klass->image, method);
10051 if (!method->token)
10052 /* Synthetic methods */
10055 idx = mono_method_get_index (method);
10056 idx <<= MONO_CUSTOM_ATTR_BITS;
10057 idx |= MONO_CUSTOM_ATTR_METHODDEF;
10058 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10061 MonoCustomAttrInfo*
10062 mono_custom_attrs_from_class (MonoClass *klass)
10065 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10066 mono_error_cleanup (&error);
10070 MonoCustomAttrInfo*
10071 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10075 mono_error_init (error);
10077 if (klass->generic_class)
10078 klass = klass->generic_class->container_class;
10080 if (image_is_dynamic (klass->image))
10081 return lookup_custom_attr (klass->image, klass);
10083 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10084 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10085 idx <<= MONO_CUSTOM_ATTR_BITS;
10086 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10088 idx = mono_metadata_token_index (klass->type_token);
10089 idx <<= MONO_CUSTOM_ATTR_BITS;
10090 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10092 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10095 MonoCustomAttrInfo*
10096 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10099 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10100 mono_error_cleanup (&error);
10104 MonoCustomAttrInfo*
10105 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10109 mono_error_init (error);
10111 if (image_is_dynamic (assembly->image))
10112 return lookup_custom_attr (assembly->image, assembly);
10113 idx = 1; /* there is only one assembly */
10114 idx <<= MONO_CUSTOM_ATTR_BITS;
10115 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10116 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10119 static MonoCustomAttrInfo*
10120 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10124 if (image_is_dynamic (image))
10125 return lookup_custom_attr (image, image);
10126 idx = 1; /* there is only one module */
10127 idx <<= MONO_CUSTOM_ATTR_BITS;
10128 idx |= MONO_CUSTOM_ATTR_MODULE;
10129 return mono_custom_attrs_from_index_checked (image, idx, error);
10132 MonoCustomAttrInfo*
10133 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10136 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10137 mono_error_cleanup (&error);
10141 MonoCustomAttrInfo*
10142 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10146 if (image_is_dynamic (klass->image)) {
10147 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10148 return lookup_custom_attr (klass->image, property);
10150 idx = find_property_index (klass, property);
10151 idx <<= MONO_CUSTOM_ATTR_BITS;
10152 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10153 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10156 MonoCustomAttrInfo*
10157 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10160 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10161 mono_error_cleanup (&error);
10165 MonoCustomAttrInfo*
10166 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10170 if (image_is_dynamic (klass->image)) {
10171 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10172 return lookup_custom_attr (klass->image, event);
10174 idx = find_event_index (klass, event);
10175 idx <<= MONO_CUSTOM_ATTR_BITS;
10176 idx |= MONO_CUSTOM_ATTR_EVENT;
10177 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10180 MonoCustomAttrInfo*
10181 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10184 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10185 mono_error_cleanup (&error);
10189 MonoCustomAttrInfo*
10190 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10193 mono_error_init (error);
10195 if (image_is_dynamic (klass->image)) {
10196 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10197 return lookup_custom_attr (klass->image, field);
10199 idx = find_field_index (klass, field);
10200 idx <<= MONO_CUSTOM_ATTR_BITS;
10201 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10202 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10206 * mono_custom_attrs_from_param:
10207 * @method: handle to the method that we want to retrieve custom parameter information from
10208 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10210 * The result must be released with mono_custom_attrs_free().
10212 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10214 MonoCustomAttrInfo*
10215 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10218 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10219 mono_error_cleanup (&error);
10224 * mono_custom_attrs_from_param_checked:
10225 * @method: handle to the method that we want to retrieve custom parameter information from
10226 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10227 * @error: set on error
10229 * The result must be released with mono_custom_attrs_free().
10231 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10233 MonoCustomAttrInfo*
10234 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10237 guint32 i, idx, method_index;
10238 guint32 param_list, param_last, param_pos, found;
10240 MonoReflectionMethodAux *aux;
10242 mono_error_init (error);
10245 * An instantiated method has the same cattrs as the generic method definition.
10247 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10248 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10250 if (method->is_inflated)
10251 method = ((MonoMethodInflated *) method)->declaring;
10253 if (image_is_dynamic (method->klass->image)) {
10254 MonoCustomAttrInfo *res, *ainfo;
10257 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10258 if (!aux || !aux->param_cattr)
10261 /* Need to copy since it will be freed later */
10262 ainfo = aux->param_cattr [param];
10265 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10266 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10267 memcpy (res, ainfo, size);
10271 image = method->klass->image;
10272 method_index = mono_method_get_index (method);
10275 ca = &image->tables [MONO_TABLE_METHOD];
10277 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10278 if (method_index == ca->rows) {
10279 ca = &image->tables [MONO_TABLE_PARAM];
10280 param_last = ca->rows + 1;
10282 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10283 ca = &image->tables [MONO_TABLE_PARAM];
10286 for (i = param_list; i < param_last; ++i) {
10287 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10288 if (param_pos == param) {
10296 idx <<= MONO_CUSTOM_ATTR_BITS;
10297 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10298 return mono_custom_attrs_from_index_checked (image, idx, error);
10302 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10306 for (i = 0; i < ainfo->num_attrs; ++i) {
10307 klass = ainfo->attrs [i].ctor->klass;
10308 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10315 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10318 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10319 mono_error_assert_ok (&error); /*FIXME proper error handling*/
10324 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10330 mono_error_init (error);
10333 for (i = 0; i < ainfo->num_attrs; ++i) {
10334 klass = ainfo->attrs [i].ctor->klass;
10335 if (mono_class_has_parent (klass, attr_klass)) {
10340 if (attr_index == -1)
10343 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10344 if (!mono_error_ok (error))
10346 return mono_array_get (attrs, MonoObject*, attr_index);
10350 * mono_reflection_get_custom_attrs_info:
10351 * @obj: a reflection object handle
10353 * Return the custom attribute info for attributes defined for the
10354 * reflection handle @obj. The objects.
10356 * FIXME this function leaks like a sieve for SRE objects.
10358 MonoCustomAttrInfo*
10359 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10362 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10363 mono_error_assert_ok (&error);
10368 * mono_reflection_get_custom_attrs_info_checked:
10369 * @obj: a reflection object handle
10370 * @error: set on error
10372 * Return the custom attribute info for attributes defined for the
10373 * reflection handle @obj. The objects.
10375 * On failure returns NULL and sets @error.
10377 * FIXME this function leaks like a sieve for SRE objects.
10379 MonoCustomAttrInfo*
10380 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10383 MonoCustomAttrInfo *cinfo = NULL;
10385 mono_error_init (error);
10387 klass = obj->vtable->klass;
10388 if (klass == mono_defaults.runtimetype_class) {
10389 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10390 return_val_if_nok (error, NULL);
10391 klass = mono_class_from_mono_type (type);
10392 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10393 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10394 return_val_if_nok (error, NULL);
10395 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10396 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10397 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10398 return_val_if_nok (error, NULL);
10399 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10400 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10401 cinfo = mono_custom_attrs_from_module (module->image, error);
10402 return_val_if_nok (error, NULL);
10403 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10404 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10405 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10406 return_val_if_nok (error, NULL);
10407 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10408 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10409 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10410 return_val_if_nok (error, NULL);
10411 } else if (strcmp ("MonoField", klass->name) == 0) {
10412 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10413 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10414 return_val_if_nok (error, NULL);
10415 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10416 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10417 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10418 return_val_if_nok (error, NULL);
10419 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10420 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10421 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10422 return_val_if_nok (error, NULL);
10423 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10424 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10425 MonoClass *member_class = mono_object_class (param->MemberImpl);
10426 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10427 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10428 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10429 return_val_if_nok (error, NULL);
10430 } else if (is_sr_mono_property (member_class)) {
10431 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10432 MonoMethod *method;
10433 if (!(method = prop->property->get))
10434 method = prop->property->set;
10437 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10438 return_val_if_nok (error, NULL);
10440 #ifndef DISABLE_REFLECTION_EMIT
10441 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10442 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10443 return_val_if_nok (error, NULL);
10444 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10445 return_val_if_nok (error, NULL);
10446 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10447 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10448 MonoMethod *method = NULL;
10449 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10450 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10451 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10452 method = ((MonoReflectionMethod *)c->cb)->method;
10454 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));
10456 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10457 return_val_if_nok (error, NULL);
10461 char *type_name = mono_type_get_full_name (member_class);
10462 mono_error_set_not_supported (error,
10463 "Custom attributes on a ParamInfo with member %s are not supported",
10465 g_free (type_name);
10468 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10469 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10470 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10471 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10472 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10473 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10474 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10475 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10476 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10477 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10478 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10479 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10480 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10481 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10482 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10483 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10484 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10485 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10486 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10487 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10488 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10489 return_val_if_nok (error, NULL);
10490 } else { /* handle other types here... */
10491 g_error ("get custom attrs not yet supported for %s", klass->name);
10498 * mono_reflection_get_custom_attrs_by_type:
10499 * @obj: a reflection object handle
10501 * Return an array with all the custom attributes defined of the
10502 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10503 * of that type are returned. The objects are fully build. Return NULL if a loading error
10507 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10510 MonoCustomAttrInfo *cinfo;
10512 mono_error_init (error);
10514 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10515 return_val_if_nok (error, NULL);
10517 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10518 if (!cinfo->cached)
10519 mono_custom_attrs_free (cinfo);
10523 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10530 * mono_reflection_get_custom_attrs:
10531 * @obj: a reflection object handle
10533 * Return an array with all the custom attributes defined of the
10534 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10538 mono_reflection_get_custom_attrs (MonoObject *obj)
10542 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10546 * mono_reflection_get_custom_attrs_data:
10547 * @obj: a reflection obj handle
10549 * Returns an array of System.Reflection.CustomAttributeData,
10550 * which include information about attributes reflected on
10551 * types loaded using the Reflection Only methods
10554 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10558 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10559 mono_error_cleanup (&error);
10564 * mono_reflection_get_custom_attrs_data_checked:
10565 * @obj: a reflection obj handle
10566 * @error: set on error
10568 * Returns an array of System.Reflection.CustomAttributeData,
10569 * which include information about attributes reflected on
10570 * types loaded using the Reflection Only methods
10573 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10576 MonoCustomAttrInfo *cinfo;
10578 mono_error_init (error);
10580 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10581 return_val_if_nok (error, NULL);
10583 result = mono_custom_attrs_data_construct (cinfo, error);
10584 if (!cinfo->cached)
10585 mono_custom_attrs_free (cinfo);
10586 return_val_if_nok (error, NULL);
10588 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10593 static MonoReflectionType*
10594 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10596 static MonoMethod *method_get_underlying_system_type = NULL;
10597 MonoReflectionType *rt;
10598 MonoMethod *usertype_method;
10600 mono_error_init (error);
10602 if (!method_get_underlying_system_type)
10603 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10605 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10607 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10614 is_corlib_type (MonoClass *klass)
10616 return klass->image == mono_defaults.corlib;
10619 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10620 static MonoClass *cached_class; \
10621 if (cached_class) \
10622 return cached_class == _class; \
10623 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10624 cached_class = _class; \
10631 #ifndef DISABLE_REFLECTION_EMIT
10633 is_sre_array (MonoClass *klass)
10635 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10639 is_sre_byref (MonoClass *klass)
10641 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10645 is_sre_pointer (MonoClass *klass)
10647 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10651 is_sre_generic_instance (MonoClass *klass)
10653 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10657 is_sre_type_builder (MonoClass *klass)
10659 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10663 is_sre_method_builder (MonoClass *klass)
10665 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10669 is_sre_ctor_builder (MonoClass *klass)
10671 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10675 is_sre_field_builder (MonoClass *klass)
10677 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10681 is_sre_method_on_tb_inst (MonoClass *klass)
10683 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10687 is_sre_ctor_on_tb_inst (MonoClass *klass)
10689 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10693 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10696 mono_error_init (error);
10703 if (is_usertype (ref)) {
10704 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10705 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10711 klass = mono_object_class (ref);
10713 if (is_sre_array (klass)) {
10715 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10716 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10717 return_val_if_nok (error, NULL);
10719 if (sre_array->rank == 0) //single dimentional array
10720 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10722 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10723 sre_array->type.type = res;
10725 } else if (is_sre_byref (klass)) {
10727 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10728 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10729 return_val_if_nok (error, NULL);
10731 res = &mono_class_from_mono_type (base)->this_arg;
10732 sre_byref->type.type = res;
10734 } else if (is_sre_pointer (klass)) {
10736 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10737 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10738 return_val_if_nok (error, NULL);
10740 res = &mono_ptr_class_get (base)->byval_arg;
10741 sre_pointer->type.type = res;
10743 } else if (is_sre_generic_instance (klass)) {
10744 MonoType *res, **types;
10745 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10748 count = mono_array_length (gclass->type_arguments);
10749 types = g_new0 (MonoType*, count);
10750 for (i = 0; i < count; ++i) {
10751 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10752 types [i] = mono_reflection_type_get_handle (t, error);
10753 if (!types[i] || !is_ok (error)) {
10759 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10762 gclass->type.type = res;
10766 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10771 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10774 mono_reflection_type_get_handle (type, &error);
10775 mono_error_set_pending_exception (&error);
10779 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10781 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10784 mono_error_init (error);
10786 MonoType *res = mono_reflection_type_get_handle (type, error);
10788 if (!res && is_ok (error)) {
10789 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10791 return_val_if_nok (error, FALSE);
10793 klass = mono_class_from_mono_type (res);
10795 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10796 mono_domain_lock (domain);
10798 if (!image_is_dynamic (klass->image)) {
10799 mono_class_setup_supertypes (klass);
10801 if (!domain->type_hash)
10802 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10803 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10804 mono_g_hash_table_insert (domain->type_hash, res, type);
10806 mono_domain_unlock (domain);
10807 mono_loader_unlock ();
10813 mono_reflection_register_with_runtime (MonoReflectionType *type)
10816 (void) reflection_register_with_runtime (type, &error);
10817 mono_error_set_pending_exception (&error);
10821 * LOCKING: Assumes the loader lock is held.
10823 static MonoMethodSignature*
10824 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10825 MonoMethodSignature *sig;
10828 mono_error_init (error);
10830 count = parameters? mono_array_length (parameters): 0;
10832 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10833 sig->param_count = count;
10834 sig->sentinelpos = -1; /* FIXME */
10835 for (i = 0; i < count; ++i) {
10836 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10837 if (!is_ok (error)) {
10838 image_g_free (image, sig);
10846 * LOCKING: Assumes the loader lock is held.
10848 static MonoMethodSignature*
10849 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10850 MonoMethodSignature *sig;
10852 mono_error_init (error);
10854 sig = parameters_to_signature (image, ctor->parameters, error);
10855 return_val_if_nok (error, NULL);
10856 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10857 sig->ret = &mono_defaults.void_class->byval_arg;
10862 * LOCKING: Assumes the loader lock is held.
10864 static MonoMethodSignature*
10865 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10866 MonoMethodSignature *sig;
10868 mono_error_init (error);
10870 sig = parameters_to_signature (image, method->parameters, error);
10871 return_val_if_nok (error, NULL);
10872 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10873 if (method->rtype) {
10874 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10875 if (!is_ok (error)) {
10876 image_g_free (image, sig);
10880 sig->ret = &mono_defaults.void_class->byval_arg;
10882 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10886 static MonoMethodSignature*
10887 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10888 MonoMethodSignature *sig;
10890 mono_error_init (error);
10892 sig = parameters_to_signature (NULL, method->parameters, error);
10893 return_val_if_nok (error, NULL);
10894 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10895 if (method->rtype) {
10896 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10897 if (!is_ok (error)) {
10902 sig->ret = &mono_defaults.void_class->byval_arg;
10904 sig->generic_param_count = 0;
10909 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10911 mono_error_init (error);
10912 MonoClass *klass = mono_object_class (prop);
10913 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10914 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10915 *name = mono_string_to_utf8_checked (pb->name, error);
10916 return_if_nok (error);
10917 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10919 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10920 *name = g_strdup (p->property->name);
10921 if (p->property->get)
10922 *type = mono_method_signature (p->property->get)->ret;
10924 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10929 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10931 mono_error_init (error);
10932 MonoClass *klass = mono_object_class (field);
10933 if (strcmp (klass->name, "FieldBuilder") == 0) {
10934 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10935 *name = mono_string_to_utf8_checked (fb->name, error);
10936 return_if_nok (error);
10937 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10939 MonoReflectionField *f = (MonoReflectionField *)field;
10940 *name = g_strdup (mono_field_get_name (f->field));
10941 *type = f->field->type;
10945 #else /* DISABLE_REFLECTION_EMIT */
10948 mono_reflection_register_with_runtime (MonoReflectionType *type)
10950 /* This is empty */
10954 is_sre_type_builder (MonoClass *klass)
10960 is_sre_generic_instance (MonoClass *klass)
10966 init_type_builder_generics (MonoObject *type, MonoError *error)
10968 mono_error_init (error);
10971 #endif /* !DISABLE_REFLECTION_EMIT */
10975 is_sr_mono_field (MonoClass *klass)
10977 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10981 is_sr_mono_property (MonoClass *klass)
10983 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10987 is_sr_mono_method (MonoClass *klass)
10989 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10993 is_sr_mono_cmethod (MonoClass *klass)
10995 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10999 is_sr_mono_generic_method (MonoClass *klass)
11001 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11005 is_sr_mono_generic_cmethod (MonoClass *klass)
11007 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11011 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11013 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11017 is_usertype (MonoReflectionType *ref)
11019 MonoClass *klass = mono_object_class (ref);
11020 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11023 static MonoReflectionType*
11024 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11026 mono_error_init (error);
11027 if (!type || type->type)
11030 if (is_usertype (type)) {
11031 type = mono_reflection_type_get_underlying_system_type (type, error);
11032 return_val_if_nok (error, NULL);
11033 if (is_usertype (type)) {
11034 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11042 * encode_cattr_value:
11043 * Encode a value in a custom attribute stream of bytes.
11044 * The value to encode is either supplied as an object in argument val
11045 * (valuetypes are boxed), or as a pointer to the data in the
11047 * @type represents the type of the value
11048 * @buffer is the start of the buffer
11049 * @p the current position in the buffer
11050 * @buflen contains the size of the buffer and is used to return the new buffer size
11051 * if this needs to be realloced.
11052 * @retbuffer and @retp return the start and the position of the buffer
11053 * @error set on error.
11056 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11058 MonoTypeEnum simple_type;
11060 mono_error_init (error);
11061 if ((p-buffer) + 10 >= *buflen) {
11064 newbuf = (char *)g_realloc (buffer, *buflen);
11065 p = newbuf + (p-buffer);
11069 argval = ((char*)arg + sizeof (MonoObject));
11070 simple_type = type->type;
11072 switch (simple_type) {
11073 case MONO_TYPE_BOOLEAN:
11078 case MONO_TYPE_CHAR:
11081 swap_with_size (p, argval, 2, 1);
11087 swap_with_size (p, argval, 4, 1);
11091 swap_with_size (p, argval, 8, 1);
11096 swap_with_size (p, argval, 8, 1);
11099 case MONO_TYPE_VALUETYPE:
11100 if (type->data.klass->enumtype) {
11101 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11104 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11107 case MONO_TYPE_STRING: {
11114 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11115 return_if_nok (error);
11116 slen = strlen (str);
11117 if ((p-buffer) + 10 + slen >= *buflen) {
11121 newbuf = (char *)g_realloc (buffer, *buflen);
11122 p = newbuf + (p-buffer);
11125 mono_metadata_encode_value (slen, p, &p);
11126 memcpy (p, str, slen);
11131 case MONO_TYPE_CLASS: {
11134 MonoType *arg_type;
11140 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11141 return_if_nok (error);
11143 str = type_get_qualified_name (arg_type, NULL);
11144 slen = strlen (str);
11145 if ((p-buffer) + 10 + slen >= *buflen) {
11149 newbuf = (char *)g_realloc (buffer, *buflen);
11150 p = newbuf + (p-buffer);
11153 mono_metadata_encode_value (slen, p, &p);
11154 memcpy (p, str, slen);
11159 case MONO_TYPE_SZARRAY: {
11161 MonoClass *eclass, *arg_eclass;
11164 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11167 len = mono_array_length ((MonoArray*)arg);
11169 *p++ = (len >> 8) & 0xff;
11170 *p++ = (len >> 16) & 0xff;
11171 *p++ = (len >> 24) & 0xff;
11173 *retbuffer = buffer;
11174 eclass = type->data.klass;
11175 arg_eclass = mono_object_class (arg)->element_class;
11178 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11179 eclass = mono_defaults.object_class;
11181 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11182 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11183 int elsize = mono_class_array_element_size (arg_eclass);
11184 for (i = 0; i < len; ++i) {
11185 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11186 return_if_nok (error);
11189 } else if (eclass->valuetype && arg_eclass->valuetype) {
11190 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11191 int elsize = mono_class_array_element_size (eclass);
11192 for (i = 0; i < len; ++i) {
11193 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11194 return_if_nok (error);
11198 for (i = 0; i < len; ++i) {
11199 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11200 return_if_nok (error);
11205 case MONO_TYPE_OBJECT: {
11211 * The parameter type is 'object' but the type of the actual
11212 * argument is not. So we have to add type information to the blob
11213 * too. This is completely undocumented in the spec.
11217 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11222 klass = mono_object_class (arg);
11224 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11228 return_if_nok (error);
11231 if (klass->enumtype) {
11233 } else if (klass == mono_defaults.string_class) {
11234 simple_type = MONO_TYPE_STRING;
11237 } else if (klass->rank == 1) {
11239 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11240 /* See Partition II, Appendix B3 */
11243 *p++ = klass->element_class->byval_arg.type;
11244 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11245 return_if_nok (error);
11247 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11248 *p++ = simple_type = klass->byval_arg.type;
11251 g_error ("unhandled type in custom attr");
11253 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11254 slen = strlen (str);
11255 if ((p-buffer) + 10 + slen >= *buflen) {
11259 newbuf = (char *)g_realloc (buffer, *buflen);
11260 p = newbuf + (p-buffer);
11263 mono_metadata_encode_value (slen, p, &p);
11264 memcpy (p, str, slen);
11267 simple_type = mono_class_enum_basetype (klass)->type;
11271 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11274 *retbuffer = buffer;
11278 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11280 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11281 char *str = type_get_qualified_name (type, NULL);
11282 int slen = strlen (str);
11286 * This seems to be optional...
11289 mono_metadata_encode_value (slen, p, &p);
11290 memcpy (p, str, slen);
11293 } else if (type->type == MONO_TYPE_OBJECT) {
11295 } else if (type->type == MONO_TYPE_CLASS) {
11296 /* it should be a type: encode_cattr_value () has the check */
11299 mono_metadata_encode_value (type->type, p, &p);
11300 if (type->type == MONO_TYPE_SZARRAY)
11301 /* See the examples in Partition VI, Annex B */
11302 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11308 #ifndef DISABLE_REFLECTION_EMIT
11310 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11314 mono_error_init (error);
11316 /* Preallocate a large enough buffer */
11317 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11318 char *str = type_get_qualified_name (type, NULL);
11319 len = strlen (str);
11321 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11322 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11323 len = strlen (str);
11328 len += strlen (name);
11330 if ((p-buffer) + 20 + len >= *buflen) {
11334 newbuf = (char *)g_realloc (buffer, *buflen);
11335 p = newbuf + (p-buffer);
11339 encode_field_or_prop_type (type, p, &p);
11341 len = strlen (name);
11342 mono_metadata_encode_value (len, p, &p);
11343 memcpy (p, name, len);
11345 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11346 return_if_nok (error);
11348 *retbuffer = buffer;
11352 * mono_reflection_get_custom_attrs_blob:
11353 * @ctor: custom attribute constructor
11354 * @ctorArgs: arguments o the constructor
11360 * Creates the blob of data that needs to be saved in the metadata and that represents
11361 * the custom attributed described by @ctor, @ctorArgs etc.
11362 * Returns: a Byte array representing the blob of data.
11365 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11368 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11369 mono_error_cleanup (&error);
11374 * mono_reflection_get_custom_attrs_blob_checked:
11375 * @ctor: custom attribute constructor
11376 * @ctorArgs: arguments o the constructor
11381 * @error: set on error
11383 * Creates the blob of data that needs to be saved in the metadata and that represents
11384 * the custom attributed described by @ctor, @ctorArgs etc.
11385 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11388 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11390 MonoArray *result = NULL;
11391 MonoMethodSignature *sig;
11396 mono_error_init (error);
11398 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11399 /* sig is freed later so allocate it in the heap */
11400 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11401 if (!is_ok (error)) {
11406 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11409 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11411 p = buffer = (char *)g_malloc (buflen);
11412 /* write the prolog */
11415 for (i = 0; i < sig->param_count; ++i) {
11416 arg = mono_array_get (ctorArgs, MonoObject*, i);
11417 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11418 if (!is_ok (error)) goto leave;
11422 i += mono_array_length (properties);
11424 i += mono_array_length (fields);
11426 *p++ = (i >> 8) & 0xff;
11429 for (i = 0; i < mono_array_length (properties); ++i) {
11433 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11434 get_prop_name_and_type (prop, &pname, &ptype, error);
11435 if (!is_ok (error)) goto leave;
11436 *p++ = 0x54; /* PROPERTY signature */
11437 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11439 if (!is_ok (error)) goto leave;
11445 for (i = 0; i < mono_array_length (fields); ++i) {
11449 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11450 get_field_name_and_type (field, &fname, &ftype, error);
11451 if (!is_ok (error)) goto leave;
11452 *p++ = 0x53; /* FIELD signature */
11453 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11455 if (!is_ok (error)) goto leave;
11459 g_assert (p - buffer <= buflen);
11460 buflen = p - buffer;
11461 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11462 if (!is_ok (error))
11464 p = mono_array_addr (result, char, 0);
11465 memcpy (p, buffer, buflen);
11468 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11474 * reflection_setup_internal_class:
11475 * @tb: a TypeBuilder object
11476 * @error: set on error
11478 * Creates a MonoClass that represents the TypeBuilder.
11479 * This is a trick that lets us simplify a lot of reflection code
11480 * (and will allow us to support Build and Run assemblies easier).
11482 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11485 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11487 MonoClass *klass, *parent;
11489 mono_error_init (error);
11490 RESOLVE_TYPE (tb->parent, error);
11491 return_val_if_nok (error, FALSE);
11493 mono_loader_lock ();
11496 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11497 if (!is_ok (error)) {
11498 mono_loader_unlock ();
11501 /* check so we can compile corlib correctly */
11502 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11503 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11504 parent = parent_type->data.klass;
11506 parent = mono_class_from_mono_type (parent_type);
11512 /* the type has already being created: it means we just have to change the parent */
11513 if (tb->type.type) {
11514 klass = mono_class_from_mono_type (tb->type.type);
11515 klass->parent = NULL;
11516 /* fool mono_class_setup_parent */
11517 klass->supertypes = NULL;
11518 mono_class_setup_parent (klass, parent);
11519 mono_class_setup_mono_type (klass);
11520 mono_loader_unlock ();
11524 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11526 klass->image = &tb->module->dynamic_image->image;
11528 klass->inited = 1; /* we lie to the runtime */
11529 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11530 if (!is_ok (error))
11532 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11533 if (!is_ok (error))
11535 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11536 klass->flags = tb->attrs;
11538 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11540 klass->element_class = klass;
11542 if (mono_class_get_ref_info (klass) == NULL) {
11544 mono_class_set_ref_info (klass, tb);
11546 /* Put into cache so mono_class_get_checked () will find it.
11547 Skip nested types as those should not be available on the global scope. */
11548 if (!tb->nesting_type)
11549 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11552 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11553 by performing a mono_class_get which does the full resolution.
11555 Working around this semantics would require us to write a lot of code for no clear advantage.
11557 mono_image_append_class_to_reflection_info_set (klass);
11559 g_assert (mono_class_get_ref_info (klass) == tb);
11562 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11564 if (parent != NULL) {
11565 mono_class_setup_parent (klass, parent);
11566 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11567 const char *old_n = klass->name;
11568 /* trick to get relative numbering right when compiling corlib */
11569 klass->name = "BuildingObject";
11570 mono_class_setup_parent (klass, mono_defaults.object_class);
11571 klass->name = old_n;
11574 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11575 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11576 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11577 klass->instance_size = sizeof (MonoObject);
11578 klass->size_inited = 1;
11579 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11582 mono_class_setup_mono_type (klass);
11584 mono_class_setup_supertypes (klass);
11587 * FIXME: handle interfaces.
11590 tb->type.type = &klass->byval_arg;
11592 if (tb->nesting_type) {
11593 g_assert (tb->nesting_type->type);
11594 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11595 if (!is_ok (error)) goto failure;
11596 klass->nested_in = mono_class_from_mono_type (nesting_type);
11599 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11601 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11603 mono_loader_unlock ();
11607 mono_loader_unlock ();
11612 * mono_reflection_setup_internal_class:
11613 * @tb: a TypeBuilder object
11616 * Creates a MonoClass that represents the TypeBuilder.
11617 * This is a trick that lets us simplify a lot of reflection code
11618 * (and will allow us to support Build and Run assemblies easier).
11622 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11625 (void) reflection_setup_internal_class (tb, &error);
11626 mono_error_set_pending_exception (&error);
11630 * mono_reflection_setup_generic_class:
11631 * @tb: a TypeBuilder object
11633 * Setup the generic class before adding the first generic parameter.
11636 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11641 * mono_reflection_create_generic_class:
11642 * @tb: a TypeBuilder object
11643 * @error: set on error
11645 * Creates the generic class after all generic parameters have been added.
11646 * On success returns TRUE, on failure returns FALSE and sets @error.
11650 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11656 mono_error_init (error);
11658 klass = mono_class_from_mono_type (tb->type.type);
11660 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11662 if (klass->generic_container || (count == 0))
11665 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11667 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11669 klass->generic_container->owner.klass = klass;
11670 klass->generic_container->type_argc = count;
11671 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11673 klass->is_generic = 1;
11675 for (i = 0; i < count; i++) {
11676 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11677 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11678 return_val_if_nok (error, FALSE);
11679 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11680 klass->generic_container->type_params [i] = *param;
11681 /*Make sure we are a diferent type instance */
11682 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11683 klass->generic_container->type_params [i].info.pklass = NULL;
11684 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11686 g_assert (klass->generic_container->type_params [i].param.owner);
11689 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11694 * reflection_create_internal_class:
11695 * @tb: a TypeBuilder object
11696 * @error: set on error
11698 * Actually create the MonoClass that is associated with the TypeBuilder.
11699 * On success returns TRUE, on failure returns FALSE and sets @error.
11703 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11708 mono_error_init (error);
11709 klass = mono_class_from_mono_type (tb->type.type);
11711 mono_loader_lock ();
11712 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11713 MonoReflectionFieldBuilder *fb;
11715 MonoType *enum_basetype;
11717 g_assert (tb->fields != NULL);
11718 g_assert (mono_array_length (tb->fields) >= 1);
11720 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11722 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11723 if (!is_ok (error)) {
11724 mono_loader_unlock ();
11727 if (!mono_type_is_valid_enum_basetype (field_type)) {
11728 mono_loader_unlock ();
11732 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11733 if (!is_ok (error)) {
11734 mono_loader_unlock ();
11737 klass->element_class = mono_class_from_mono_type (enum_basetype);
11738 if (!klass->element_class)
11739 klass->element_class = mono_class_from_mono_type (enum_basetype);
11742 * get the element_class from the current corlib.
11744 ec = default_class_from_mono_type (enum_basetype);
11745 klass->instance_size = ec->instance_size;
11746 klass->size_inited = 1;
11748 * this is almost safe to do with enums and it's needed to be able
11749 * to create objects of the enum type (for use in SetConstant).
11751 /* FIXME: Does this mean enums can't have method overrides ? */
11752 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11754 mono_loader_unlock ();
11759 * mono_reflection_create_internal_class:
11760 * @tb: a TypeBuilder object
11763 * Actually create the MonoClass that is associated with the TypeBuilder.
11766 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11769 (void) reflection_create_internal_class (tb, &error);
11770 mono_error_set_pending_exception (&error);
11773 static MonoMarshalSpec*
11774 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11775 MonoReflectionMarshal *minfo, MonoError *error)
11777 MonoMarshalSpec *res;
11779 mono_error_init (error);
11781 res = image_g_new0 (image, MonoMarshalSpec, 1);
11782 res->native = (MonoMarshalNative)minfo->type;
11784 switch (minfo->type) {
11785 case MONO_NATIVE_LPARRAY:
11786 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11787 if (minfo->has_size) {
11788 res->data.array_data.param_num = minfo->param_num;
11789 res->data.array_data.num_elem = minfo->count;
11790 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11793 res->data.array_data.param_num = -1;
11794 res->data.array_data.num_elem = -1;
11795 res->data.array_data.elem_mult = -1;
11799 case MONO_NATIVE_BYVALTSTR:
11800 case MONO_NATIVE_BYVALARRAY:
11801 res->data.array_data.num_elem = minfo->count;
11804 case MONO_NATIVE_CUSTOM:
11805 if (minfo->marshaltyperef) {
11806 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11807 if (!is_ok (error)) {
11808 image_g_free (image, res);
11811 res->data.custom_data.custom_name =
11812 type_get_fully_qualified_name (marshaltyperef);
11814 if (minfo->mcookie) {
11815 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11816 if (!is_ok (error)) {
11817 image_g_free (image, res);
11829 #endif /* !DISABLE_REFLECTION_EMIT */
11831 MonoReflectionMarshalAsAttribute*
11832 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11833 MonoMarshalSpec *spec, MonoError *error)
11835 MonoReflectionType *rt;
11836 MonoReflectionMarshalAsAttribute *minfo;
11839 mono_error_init (error);
11841 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11844 minfo->utype = spec->native;
11846 switch (minfo->utype) {
11847 case MONO_NATIVE_LPARRAY:
11848 minfo->array_subtype = spec->data.array_data.elem_type;
11849 minfo->size_const = spec->data.array_data.num_elem;
11850 if (spec->data.array_data.param_num != -1)
11851 minfo->size_param_index = spec->data.array_data.param_num;
11854 case MONO_NATIVE_BYVALTSTR:
11855 case MONO_NATIVE_BYVALARRAY:
11856 minfo->size_const = spec->data.array_data.num_elem;
11859 case MONO_NATIVE_CUSTOM:
11860 if (spec->data.custom_data.custom_name) {
11861 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11862 return_val_if_nok (error, NULL);
11865 rt = mono_type_get_object_checked (domain, mtype, error);
11869 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11872 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11874 if (spec->data.custom_data.cookie)
11875 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11885 #ifndef DISABLE_REFLECTION_EMIT
11887 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11888 ReflectionMethodBuilder *rmb,
11889 MonoMethodSignature *sig,
11893 MonoMethodWrapper *wrapperm;
11894 MonoMarshalSpec **specs;
11895 MonoReflectionMethodAux *method_aux;
11900 mono_error_init (error);
11902 * Methods created using a MethodBuilder should have their memory allocated
11903 * inside the image mempool, while dynamic methods should have their memory
11906 dynamic = rmb->refs != NULL;
11907 image = dynamic ? NULL : klass->image;
11910 g_assert (!klass->generic_class);
11912 mono_loader_lock ();
11914 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11915 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11916 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11918 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11920 wrapperm = (MonoMethodWrapper*)m;
11922 m->dynamic = dynamic;
11924 m->flags = rmb->attrs;
11925 m->iflags = rmb->iattrs;
11926 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11928 m->signature = sig;
11929 m->sre_method = TRUE;
11930 m->skip_visibility = rmb->skip_visibility;
11931 if (rmb->table_idx)
11932 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11934 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11935 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11936 m->string_ctor = 1;
11938 m->signature->pinvoke = 1;
11939 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11940 m->signature->pinvoke = 1;
11942 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11944 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11945 mono_error_assert_ok (error);
11946 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11947 mono_error_assert_ok (error);
11949 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11951 if (image_is_dynamic (klass->image))
11952 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11954 mono_loader_unlock ();
11957 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11958 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11959 MonoMethodHeader *header;
11961 gint32 max_stack, i;
11962 gint32 num_locals = 0;
11963 gint32 num_clauses = 0;
11967 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11968 code_size = rmb->ilgen->code_len;
11969 max_stack = rmb->ilgen->max_stack;
11970 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11971 if (rmb->ilgen->ex_handlers)
11972 num_clauses = method_count_clauses (rmb->ilgen);
11975 code = mono_array_addr (rmb->code, guint8, 0);
11976 code_size = mono_array_length (rmb->code);
11977 /* we probably need to run a verifier on the code... */
11987 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11988 header->code_size = code_size;
11989 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11990 memcpy ((char*)header->code, code, code_size);
11991 header->max_stack = max_stack;
11992 header->init_locals = rmb->init_locals;
11993 header->num_locals = num_locals;
11995 for (i = 0; i < num_locals; ++i) {
11996 MonoReflectionLocalBuilder *lb =
11997 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11999 header->locals [i] = image_g_new0 (image, MonoType, 1);
12000 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12001 mono_error_assert_ok (error);
12002 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12005 header->num_clauses = num_clauses;
12007 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12008 rmb->ilgen, num_clauses, error);
12009 mono_error_assert_ok (error);
12012 wrapperm->header = header;
12015 if (rmb->generic_params) {
12016 int count = mono_array_length (rmb->generic_params);
12017 MonoGenericContainer *container = rmb->generic_container;
12019 g_assert (container);
12021 container->type_argc = count;
12022 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12023 container->owner.method = m;
12024 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12026 m->is_generic = TRUE;
12027 mono_method_set_generic_container (m, container);
12029 for (i = 0; i < count; i++) {
12030 MonoReflectionGenericParam *gp =
12031 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12032 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12033 mono_error_assert_ok (error);
12034 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12035 container->type_params [i] = *param;
12039 * The method signature might have pointers to generic parameters that belong to other methods.
12040 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12041 * generic parameters.
12043 for (i = 0; i < m->signature->param_count; ++i) {
12044 MonoType *t = m->signature->params [i];
12045 if (t->type == MONO_TYPE_MVAR) {
12046 MonoGenericParam *gparam = t->data.generic_param;
12047 if (gparam->num < count) {
12048 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12049 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12055 if (klass->generic_container) {
12056 container->parent = klass->generic_container;
12057 container->context.class_inst = klass->generic_container->context.class_inst;
12059 container->context.method_inst = mono_get_shared_generic_inst (container);
12063 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12067 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12069 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12070 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12071 for (i = 0; i < rmb->nrefs; ++i)
12072 data [i + 1] = rmb->refs [i];
12077 /* Parameter info */
12080 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12081 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12082 for (i = 0; i <= m->signature->param_count; ++i) {
12083 MonoReflectionParamBuilder *pb;
12084 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12085 if ((i > 0) && (pb->attrs)) {
12086 /* Make a copy since it might point to a shared type structure */
12087 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12088 m->signature->params [i - 1]->attrs = pb->attrs;
12091 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12092 MonoDynamicImage *assembly;
12094 MonoTypeEnum def_type;
12098 if (!method_aux->param_defaults) {
12099 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12100 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12102 assembly = (MonoDynamicImage*)klass->image;
12103 idx = encode_constant (assembly, pb->def_value, &def_type);
12104 /* Copy the data from the blob since it might get realloc-ed */
12105 p = assembly->blob.data + idx;
12106 len = mono_metadata_decode_blob_size (p, &p2);
12108 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12109 method_aux->param_default_types [i] = def_type;
12110 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12114 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12115 mono_error_assert_ok (error);
12118 if (!method_aux->param_cattr)
12119 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12120 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12126 /* Parameter marshalling */
12129 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12130 MonoReflectionParamBuilder *pb;
12131 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12132 if (pb->marshal_info) {
12134 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12135 specs [pb->position] =
12136 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12137 if (!is_ok (error)) {
12138 mono_loader_unlock ();
12139 image_g_free (image, specs);
12140 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12146 if (specs != NULL) {
12148 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12149 method_aux->param_marshall = specs;
12152 if (image_is_dynamic (klass->image) && method_aux)
12153 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12155 mono_loader_unlock ();
12161 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12163 ReflectionMethodBuilder rmb;
12164 MonoMethodSignature *sig;
12166 mono_loader_lock ();
12167 g_assert (klass->image != NULL);
12168 sig = ctor_builder_to_signature (klass->image, mb, error);
12169 mono_loader_unlock ();
12170 return_val_if_nok (error, NULL);
12172 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12175 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12176 return_val_if_nok (error, NULL);
12177 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12179 /* If we are in a generic class, we might be called multiple times from inflate_method */
12180 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12181 /* ilgen is no longer needed */
12185 return mb->mhandle;
12189 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12191 ReflectionMethodBuilder rmb;
12192 MonoMethodSignature *sig;
12194 mono_error_init (error);
12196 mono_loader_lock ();
12197 g_assert (klass->image != NULL);
12198 sig = method_builder_to_signature (klass->image, mb, error);
12199 mono_loader_unlock ();
12200 return_val_if_nok (error, NULL);
12202 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12205 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12206 return_val_if_nok (error, NULL);
12207 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12209 /* If we are in a generic class, we might be called multiple times from inflate_method */
12210 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12211 /* ilgen is no longer needed */
12214 return mb->mhandle;
12217 static MonoClassField*
12218 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12220 MonoClassField *field;
12223 mono_error_init (error);
12225 field = g_new0 (MonoClassField, 1);
12227 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12228 mono_error_assert_ok (error);
12229 if (fb->attrs || fb->modreq || fb->modopt) {
12230 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12231 if (!is_ok (error)) {
12235 field->type = mono_metadata_type_dup (NULL, type);
12236 field->type->attrs = fb->attrs;
12238 g_assert (image_is_dynamic (klass->image));
12239 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12240 g_free (field->type);
12241 if (!is_ok (error)) {
12245 field->type = mono_metadata_type_dup (klass->image, custom);
12248 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12249 if (!is_ok (error)) {
12254 if (fb->offset != -1)
12255 field->offset = fb->offset;
12256 field->parent = klass;
12257 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12259 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12266 * mono_reflection_bind_generic_parameters:
12267 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12268 * @type_args: the number of type arguments to bind
12269 * @types: array of type arguments
12270 * @error: set on error
12272 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12273 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12276 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12279 MonoReflectionTypeBuilder *tb = NULL;
12280 gboolean is_dynamic = FALSE;
12281 MonoClass *geninst;
12283 mono_error_init (error);
12285 mono_loader_lock ();
12287 if (is_sre_type_builder (mono_object_class (type))) {
12288 tb = (MonoReflectionTypeBuilder *) type;
12291 } else if (is_sre_generic_instance (mono_object_class (type))) {
12292 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12293 MonoReflectionType *gtd = rgi->generic_type;
12295 if (is_sre_type_builder (mono_object_class (gtd))) {
12296 tb = (MonoReflectionTypeBuilder *)gtd;
12301 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12302 if (tb && tb->generic_container) {
12303 if (!mono_reflection_create_generic_class (tb, error)) {
12304 mono_loader_unlock ();
12309 MonoType *t = mono_reflection_type_get_handle (type, error);
12310 if (!is_ok (error)) {
12311 mono_loader_unlock ();
12315 klass = mono_class_from_mono_type (t);
12316 if (!klass->generic_container) {
12317 mono_loader_unlock ();
12318 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12322 if (klass->wastypebuilder) {
12323 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12328 mono_loader_unlock ();
12330 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12332 return &geninst->byval_arg;
12336 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12338 MonoGenericClass *gclass;
12339 MonoGenericInst *inst;
12341 g_assert (klass->generic_container);
12343 inst = mono_metadata_get_generic_inst (type_argc, types);
12344 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12346 return mono_generic_class_get_class (gclass);
12349 static MonoReflectionMethod*
12350 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12353 MonoMethod *method, *inflated;
12354 MonoMethodInflated *imethod;
12355 MonoGenericContext tmp_context;
12356 MonoGenericInst *ginst;
12357 MonoType **type_argv;
12360 mono_error_init (error);
12362 /*FIXME but this no longer should happen*/
12363 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12364 #ifndef DISABLE_REFLECTION_EMIT
12365 MonoReflectionMethodBuilder *mb = NULL;
12369 mb = (MonoReflectionMethodBuilder *) rmethod;
12370 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12371 return_val_if_nok (error, NULL);
12372 klass = mono_class_from_mono_type (tb);
12374 method = methodbuilder_to_mono_method (klass, mb, error);
12375 return_val_if_nok (error, NULL);
12377 g_assert_not_reached ();
12381 method = rmethod->method;
12384 klass = method->klass;
12386 if (method->is_inflated)
12387 method = ((MonoMethodInflated *) method)->declaring;
12389 count = mono_method_signature (method)->generic_param_count;
12390 if (count != mono_array_length (types))
12393 type_argv = g_new0 (MonoType *, count);
12394 for (i = 0; i < count; i++) {
12395 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12396 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12397 if (!is_ok (error)) {
12398 g_free (type_argv);
12402 ginst = mono_metadata_get_generic_inst (count, type_argv);
12403 g_free (type_argv);
12405 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12406 tmp_context.method_inst = ginst;
12408 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12409 mono_error_assert_ok (error);
12410 imethod = (MonoMethodInflated *) inflated;
12412 /*FIXME but I think this is no longer necessary*/
12413 if (image_is_dynamic (method->klass->image)) {
12414 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12416 * This table maps metadata structures representing inflated methods/fields
12417 * to the reflection objects representing their generic definitions.
12419 mono_image_lock ((MonoImage*)image);
12420 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12421 mono_image_unlock ((MonoImage*)image);
12424 if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12425 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12429 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12433 MonoReflectionMethod*
12434 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12437 MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12438 mono_error_set_pending_exception (&error);
12443 #ifndef DISABLE_REFLECTION_EMIT
12445 static MonoMethod *
12446 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12448 MonoMethodInflated *imethod;
12449 MonoGenericContext *context;
12453 * With generic code sharing the klass might not be inflated.
12454 * This can happen because classes inflated with their own
12455 * type arguments are "normalized" to the uninflated class.
12457 if (!klass->generic_class)
12460 context = mono_class_get_context (klass);
12462 if (klass->method.count && klass->methods) {
12463 /* Find the already created inflated method */
12464 for (i = 0; i < klass->method.count; ++i) {
12465 g_assert (klass->methods [i]->is_inflated);
12466 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12469 g_assert (i < klass->method.count);
12470 imethod = (MonoMethodInflated*)klass->methods [i];
12473 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12474 mono_error_assert_ok (&error);
12477 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12478 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12480 mono_image_lock ((MonoImage*)image);
12481 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12482 mono_image_unlock ((MonoImage*)image);
12484 return (MonoMethod *) imethod;
12487 static MonoMethod *
12488 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12490 MonoMethod *method;
12493 mono_error_init (error);
12495 MonoClass *type_class = mono_object_class (type);
12497 if (is_sre_generic_instance (type_class)) {
12498 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12499 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12500 return_val_if_nok (error, NULL);
12501 gklass = mono_class_from_mono_type (generic_type);
12502 } else if (is_sre_type_builder (type_class)) {
12503 MonoType *t = mono_reflection_type_get_handle (type, error);
12504 return_val_if_nok (error, NULL);
12505 gklass = mono_class_from_mono_type (t);
12506 } else if (type->type) {
12507 gklass = mono_class_from_mono_type (type->type);
12508 gklass = mono_class_get_generic_type_definition (gklass);
12510 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12513 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12514 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12515 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12517 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12521 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12522 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12525 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12526 method = ((MonoReflectionMethod *) obj)->method;
12528 method = NULL; /* prevent compiler warning */
12529 g_error ("can't handle type %s", obj->vtable->klass->name);
12532 MonoType *t = mono_reflection_type_get_handle (type, error);
12533 return_val_if_nok (error, NULL);
12534 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12537 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12539 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12541 MonoGenericClass *gclass;
12542 MonoDynamicGenericClass *dgclass;
12543 MonoClass *klass, *gklass;
12547 mono_error_init (error);
12549 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12550 return_val_if_nok (error, FALSE);
12551 klass = mono_class_from_mono_type (gtype);
12552 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12553 gclass = gtype->data.generic_class;
12555 if (!gclass->is_dynamic)
12558 dgclass = (MonoDynamicGenericClass *) gclass;
12560 if (dgclass->initialized)
12563 gklass = gclass->container_class;
12564 mono_class_init (gklass);
12566 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12568 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12569 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12570 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12572 for (i = 0; i < dgclass->count_fields; i++) {
12573 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12574 MonoClassField *field, *inflated_field = NULL;
12576 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12577 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12578 return_val_if_nok (error, FALSE);
12579 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12580 field = ((MonoReflectionField *) obj)->field;
12582 field = NULL; /* prevent compiler warning */
12583 g_assert_not_reached ();
12586 dgclass->fields [i] = *field;
12587 dgclass->fields [i].parent = klass;
12588 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12589 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12590 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12591 dgclass->field_generic_types [i] = field->type;
12592 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12593 dgclass->field_objects [i] = obj;
12595 if (inflated_field) {
12596 g_free (inflated_field);
12598 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12602 dgclass->initialized = TRUE;
12607 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12610 (void) reflection_generic_class_initialize (type, fields, &error);
12611 mono_error_set_pending_exception (&error);
12615 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12617 MonoDynamicGenericClass *dgclass;
12620 g_assert (gclass->is_dynamic);
12622 dgclass = (MonoDynamicGenericClass *)gclass;
12624 for (i = 0; i < dgclass->count_fields; ++i) {
12625 MonoClassField *field = dgclass->fields + i;
12626 mono_metadata_free_type (field->type);
12627 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12632 * fix_partial_generic_class:
12633 * @klass: a generic instantiation MonoClass
12634 * @error: set on error
12636 * Assumes that the generic container of @klass has its vtable
12637 * initialized, and updates the parent class, insterfaces, methods and
12638 * fields of @klass by inflating the types using the generic context.
12640 * On success returns TRUE, on failure returns FALSE and sets @error.
12644 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12646 MonoClass *gklass = klass->generic_class->container_class;
12647 MonoDynamicGenericClass *dgclass;
12650 mono_error_init (error);
12652 if (klass->wastypebuilder)
12655 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12656 if (klass->parent != gklass->parent) {
12657 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12658 if (mono_error_ok (error)) {
12659 MonoClass *parent = mono_class_from_mono_type (parent_type);
12660 mono_metadata_free_type (parent_type);
12661 if (parent != klass->parent) {
12662 /*fool mono_class_setup_parent*/
12663 klass->supertypes = NULL;
12664 mono_class_setup_parent (klass, parent);
12667 if (gklass->wastypebuilder)
12668 klass->wastypebuilder = TRUE;
12673 if (!dgclass->initialized)
12676 if (klass->method.count != gklass->method.count) {
12677 klass->method.count = gklass->method.count;
12678 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12680 for (i = 0; i < klass->method.count; i++) {
12681 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12682 gklass->methods [i], klass, mono_class_get_context (klass), error);
12683 mono_error_assert_ok (error);
12687 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12688 klass->interface_count = gklass->interface_count;
12689 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12690 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12692 for (i = 0; i < gklass->interface_count; ++i) {
12693 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12694 return_val_if_nok (error, FALSE);
12696 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12697 mono_metadata_free_type (iface_type);
12699 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12702 klass->interfaces_inited = 1;
12705 if (klass->field.count != gklass->field.count) {
12706 klass->field.count = gklass->field.count;
12707 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12709 for (i = 0; i < klass->field.count; i++) {
12710 klass->fields [i] = gklass->fields [i];
12711 klass->fields [i].parent = klass;
12712 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12713 return_val_if_nok (error, FALSE);
12717 /*We can only finish with this klass once it's parent has as well*/
12718 if (gklass->wastypebuilder)
12719 klass->wastypebuilder = TRUE;
12724 * ensure_generic_class_runtime_vtable:
12725 * @klass a generic class
12726 * @error set on error
12728 * Ensures that the generic container of @klass has a vtable and
12729 * returns TRUE on success. On error returns FALSE and sets @error.
12732 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12734 MonoClass *gklass = klass->generic_class->container_class;
12736 mono_error_init (error);
12738 if (!ensure_runtime_vtable (gklass, error))
12741 return fix_partial_generic_class (klass, error);
12745 * ensure_runtime_vtable:
12747 * @error set on error
12749 * Ensures that @klass has a vtable and returns TRUE on success. On
12750 * error returns FALSE and sets @error.
12753 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12755 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12758 mono_error_init (error);
12760 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12763 if (!ensure_runtime_vtable (klass->parent, error))
12767 num = tb->ctors? mono_array_length (tb->ctors): 0;
12768 num += tb->num_methods;
12769 klass->method.count = num;
12770 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12771 num = tb->ctors? mono_array_length (tb->ctors): 0;
12772 for (i = 0; i < num; ++i) {
12773 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12776 klass->methods [i] = ctor;
12778 num = tb->num_methods;
12780 for (i = 0; i < num; ++i) {
12781 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12784 klass->methods [j++] = meth;
12787 if (tb->interfaces) {
12788 klass->interface_count = mono_array_length (tb->interfaces);
12789 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12790 for (i = 0; i < klass->interface_count; ++i) {
12791 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12792 return_val_if_nok (error, FALSE);
12793 klass->interfaces [i] = mono_class_from_mono_type (iface);
12794 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12797 klass->interfaces_inited = 1;
12799 } else if (klass->generic_class){
12800 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12801 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12806 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12808 for (i = 0; i < klass->method.count; ++i) {
12809 MonoMethod *im = klass->methods [i];
12810 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12811 im->slot = slot_num++;
12814 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12815 mono_class_setup_interface_offsets (klass);
12816 mono_class_setup_interface_id (klass);
12820 * The generic vtable is needed even if image->run is not set since some
12821 * runtime code like ves_icall_Type_GetMethodsByName depends on
12822 * method->slot being defined.
12826 * tb->methods could not be freed since it is used for determining
12827 * overrides during dynamic vtable construction.
12834 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12836 mono_error_init (error);
12837 MonoClass *klass = mono_object_class (method);
12838 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12839 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12840 return sr_method->method;
12842 if (is_sre_method_builder (klass)) {
12843 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12844 return mb->mhandle;
12846 if (is_sre_method_on_tb_inst (klass)) {
12847 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12848 MonoMethod *result;
12849 /*FIXME move this to a proper method and unify with resolve_object*/
12850 if (m->method_args) {
12851 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12853 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12854 return_val_if_nok (error, NULL);
12855 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12856 MonoMethod *mono_method;
12858 if (is_sre_method_builder (mono_object_class (m->mb)))
12859 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12860 else if (is_sr_mono_method (mono_object_class (m->mb)))
12861 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12863 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)));
12865 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12870 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12875 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12877 MonoReflectionTypeBuilder *tb;
12879 MonoReflectionMethod *m;
12881 mono_error_init (error);
12883 *num_overrides = 0;
12885 g_assert (image_is_dynamic (klass->image));
12887 if (!mono_class_get_ref_info (klass))
12890 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12892 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12896 for (i = 0; i < tb->num_methods; ++i) {
12897 MonoReflectionMethodBuilder *mb =
12898 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12899 if (mb->override_methods)
12900 onum += mono_array_length (mb->override_methods);
12905 *overrides = g_new0 (MonoMethod*, onum * 2);
12908 for (i = 0; i < tb->num_methods; ++i) {
12909 MonoReflectionMethodBuilder *mb =
12910 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12911 if (mb->override_methods) {
12912 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12913 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12915 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12916 return_if_nok (error);
12917 (*overrides) [onum * 2 + 1] = mb->mhandle;
12919 g_assert (mb->mhandle);
12927 *num_overrides = onum;
12931 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12933 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12934 MonoReflectionFieldBuilder *fb;
12935 MonoClassField *field;
12936 MonoImage *image = klass->image;
12937 const char *p, *p2;
12939 guint32 len, idx, real_size = 0;
12941 klass->field.count = tb->num_fields;
12942 klass->field.first = 0;
12944 mono_error_init (error);
12946 if (tb->class_size) {
12947 if ((tb->packing_size & 0xffffff00) != 0) {
12948 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12949 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12952 klass->packing_size = tb->packing_size;
12953 real_size = klass->instance_size + tb->class_size;
12956 if (!klass->field.count) {
12957 klass->instance_size = MAX (klass->instance_size, real_size);
12961 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12962 mono_class_alloc_ext (klass);
12963 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12965 This is, guess what, a hack.
12966 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12967 On the static path no field class is resolved, only types are built. This is the right thing to do
12969 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12971 klass->size_inited = 1;
12973 for (i = 0; i < klass->field.count; ++i) {
12974 MonoArray *rva_data;
12975 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12976 field = &klass->fields [i];
12977 field->name = mono_string_to_utf8_image (image, fb->name, error);
12978 if (!mono_error_ok (error))
12981 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12982 return_if_nok (error);
12983 field->type = mono_metadata_type_dup (klass->image, type);
12984 field->type->attrs = fb->attrs;
12986 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12987 return_if_nok (error);
12990 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12991 char *base = mono_array_addr (rva_data, char, 0);
12992 size_t size = mono_array_length (rva_data);
12993 char *data = (char *)mono_image_alloc (klass->image, size);
12994 memcpy (data, base, size);
12995 klass->ext->field_def_values [i].data = data;
12997 if (fb->offset != -1)
12998 field->offset = fb->offset;
12999 field->parent = klass;
13000 fb->handle = field;
13001 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13003 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13004 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13006 if (fb->def_value) {
13007 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13008 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13009 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13010 /* Copy the data from the blob since it might get realloc-ed */
13011 p = assembly->blob.data + idx;
13012 len = mono_metadata_decode_blob_size (p, &p2);
13014 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13015 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13019 klass->instance_size = MAX (klass->instance_size, real_size);
13020 mono_class_layout_fields (klass, klass->instance_size);
13024 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13026 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13027 MonoReflectionPropertyBuilder *pb;
13028 MonoImage *image = klass->image;
13029 MonoProperty *properties;
13032 mono_error_init (error);
13035 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13037 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13038 klass->ext->property.first = 0;
13040 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13041 klass->ext->properties = properties;
13042 for (i = 0; i < klass->ext->property.count; ++i) {
13043 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13044 properties [i].parent = klass;
13045 properties [i].attrs = pb->attrs;
13046 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13047 if (!mono_error_ok (error))
13049 if (pb->get_method)
13050 properties [i].get = pb->get_method->mhandle;
13051 if (pb->set_method)
13052 properties [i].set = pb->set_method->mhandle;
13054 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13055 if (pb->def_value) {
13057 const char *p, *p2;
13058 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13059 if (!klass->ext->prop_def_values)
13060 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13061 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13062 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13063 /* Copy the data from the blob since it might get realloc-ed */
13064 p = assembly->blob.data + idx;
13065 len = mono_metadata_decode_blob_size (p, &p2);
13067 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13068 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13073 static MonoReflectionEvent *
13074 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13076 mono_error_init (error);
13078 MonoEvent *event = g_new0 (MonoEvent, 1);
13081 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13082 if (!is_ok (error)) {
13086 klass = mono_class_from_mono_type (type);
13088 event->parent = klass;
13089 event->attrs = eb->attrs;
13090 event->name = mono_string_to_utf8_checked (eb->name, error);
13091 if (!is_ok (error)) {
13095 if (eb->add_method)
13096 event->add = eb->add_method->mhandle;
13097 if (eb->remove_method)
13098 event->remove = eb->remove_method->mhandle;
13099 if (eb->raise_method)
13100 event->raise = eb->raise_method->mhandle;
13102 #ifndef MONO_SMALL_CONFIG
13103 if (eb->other_methods) {
13105 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13106 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13107 MonoReflectionMethodBuilder *mb =
13108 mono_array_get (eb->other_methods,
13109 MonoReflectionMethodBuilder*, j);
13110 event->other [j] = mb->mhandle;
13115 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13116 if (!is_ok (error)) {
13117 #ifndef MONO_SMALL_CONFIG
13118 g_free (event->other);
13126 MonoReflectionEvent *
13127 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13130 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13131 mono_error_set_pending_exception (&error);
13136 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13138 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13139 MonoReflectionEventBuilder *eb;
13140 MonoImage *image = klass->image;
13144 mono_error_init (error);
13147 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13149 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13150 klass->ext->event.first = 0;
13152 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13153 klass->ext->events = events;
13154 for (i = 0; i < klass->ext->event.count; ++i) {
13155 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13156 events [i].parent = klass;
13157 events [i].attrs = eb->attrs;
13158 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13159 if (!mono_error_ok (error))
13161 if (eb->add_method)
13162 events [i].add = eb->add_method->mhandle;
13163 if (eb->remove_method)
13164 events [i].remove = eb->remove_method->mhandle;
13165 if (eb->raise_method)
13166 events [i].raise = eb->raise_method->mhandle;
13168 #ifndef MONO_SMALL_CONFIG
13169 if (eb->other_methods) {
13171 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13172 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13173 MonoReflectionMethodBuilder *mb =
13174 mono_array_get (eb->other_methods,
13175 MonoReflectionMethodBuilder*, j);
13176 events [i].other [j] = mb->mhandle;
13180 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13184 struct remove_instantiations_user_data
13191 remove_instantiations_of_and_ensure_contents (gpointer key,
13193 gpointer user_data)
13195 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13196 MonoType *type = (MonoType*)key;
13197 MonoClass *klass = data->klass;
13198 gboolean already_failed = !is_ok (data->error);
13200 MonoError *error = already_failed ? &lerror : data->error;
13202 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13203 MonoClass *inst_klass = mono_class_from_mono_type (type);
13204 //Ensure it's safe to use it.
13205 if (!fix_partial_generic_class (inst_klass, error)) {
13206 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13207 // Marked the class with failure, but since some other instantiation already failed,
13208 // just report that one, and swallow the error from this one.
13209 if (already_failed)
13210 mono_error_cleanup (error);
13218 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13220 mono_error_init (error);
13226 for (i = 0; i < mono_array_length (arr); ++i) {
13227 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13228 if (!mono_error_ok (error))
13233 MonoReflectionType*
13234 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13238 MonoDomain* domain;
13239 MonoReflectionType* res;
13242 mono_error_init (&error);
13244 domain = mono_object_domain (tb);
13245 klass = mono_class_from_mono_type (tb->type.type);
13248 * Check for user defined Type subclasses.
13250 RESOLVE_TYPE (tb->parent, &error);
13251 if (!is_ok (&error))
13252 goto failure_unlocked;
13253 check_array_for_usertypes (tb->interfaces, &error);
13254 if (!is_ok (&error))
13255 goto failure_unlocked;
13257 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13258 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13260 RESOLVE_TYPE (fb->type, &error);
13261 if (!is_ok (&error))
13262 goto failure_unlocked;
13263 check_array_for_usertypes (fb->modreq, &error);
13264 if (!is_ok (&error))
13265 goto failure_unlocked;
13266 check_array_for_usertypes (fb->modopt, &error);
13267 if (!is_ok (&error))
13268 goto failure_unlocked;
13269 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13270 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13271 if (!is_ok (&error))
13272 goto failure_unlocked;
13278 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13279 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13281 RESOLVE_TYPE (mb->rtype, &error);
13282 if (!is_ok (&error))
13283 goto failure_unlocked;
13284 check_array_for_usertypes (mb->return_modreq, &error);
13285 if (!is_ok (&error))
13286 goto failure_unlocked;
13287 check_array_for_usertypes (mb->return_modopt, &error);
13288 if (!is_ok (&error))
13289 goto failure_unlocked;
13290 check_array_for_usertypes (mb->parameters, &error);
13291 if (!is_ok (&error))
13292 goto failure_unlocked;
13293 if (mb->param_modreq)
13294 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13295 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13296 if (!is_ok (&error))
13297 goto failure_unlocked;
13299 if (mb->param_modopt)
13300 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13301 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13302 if (!is_ok (&error))
13303 goto failure_unlocked;
13309 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13310 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13312 check_array_for_usertypes (mb->parameters, &error);
13313 if (!is_ok (&error))
13314 goto failure_unlocked;
13315 if (mb->param_modreq)
13316 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13317 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13318 if (!is_ok (&error))
13319 goto failure_unlocked;
13321 if (mb->param_modopt)
13322 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13323 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13324 if (!is_ok (&error))
13325 goto failure_unlocked;
13331 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13334 * we need to lock the domain because the lock will be taken inside
13335 * So, we need to keep the locking order correct.
13337 mono_loader_lock ();
13338 mono_domain_lock (domain);
13339 if (klass->wastypebuilder) {
13340 mono_domain_unlock (domain);
13341 mono_loader_unlock ();
13343 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13344 mono_error_set_pending_exception (&error);
13349 * Fields to set in klass:
13350 * the various flags: delegate/unicode/contextbound etc.
13352 klass->flags = tb->attrs;
13353 klass->has_cctor = 1;
13355 mono_class_setup_parent (klass, klass->parent);
13356 /* fool mono_class_setup_supertypes */
13357 klass->supertypes = NULL;
13358 mono_class_setup_supertypes (klass);
13359 mono_class_setup_mono_type (klass);
13362 if (!((MonoDynamicImage*)klass->image)->run) {
13363 if (klass->generic_container) {
13364 /* FIXME: The code below can't handle generic classes */
13365 klass->wastypebuilder = TRUE;
13366 mono_loader_unlock ();
13367 mono_domain_unlock (domain);
13369 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13370 mono_error_set_pending_exception (&error);
13377 /* enums are done right away */
13378 if (!klass->enumtype)
13379 if (!ensure_runtime_vtable (klass, &error))
13382 if (tb->subtypes) {
13383 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13384 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13385 mono_class_alloc_ext (klass);
13386 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13387 if (!is_ok (&error)) goto failure;
13388 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13392 klass->nested_classes_inited = TRUE;
13394 /* fields and object layout */
13395 if (klass->parent) {
13396 if (!klass->parent->size_inited)
13397 mono_class_init (klass->parent);
13398 klass->instance_size = klass->parent->instance_size;
13399 klass->sizes.class_size = 0;
13400 klass->min_align = klass->parent->min_align;
13401 /* if the type has no fields we won't call the field_setup
13402 * routine which sets up klass->has_references.
13404 klass->has_references |= klass->parent->has_references;
13406 klass->instance_size = sizeof (MonoObject);
13407 klass->min_align = 1;
13410 /* FIXME: handle packing_size and instance_size */
13411 typebuilder_setup_fields (klass, &error);
13412 if (!mono_error_ok (&error))
13414 typebuilder_setup_properties (klass, &error);
13415 if (!mono_error_ok (&error))
13418 typebuilder_setup_events (klass, &error);
13419 if (!mono_error_ok (&error))
13422 klass->wastypebuilder = TRUE;
13425 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13426 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13427 * we want to return normal System.MonoType objects, so clear these out from the cache.
13429 * Together with this we must ensure the contents of all instances to match the created type.
13431 if (domain->type_hash && klass->generic_container) {
13432 struct remove_instantiations_user_data data;
13433 data.klass = klass;
13434 data.error = &error;
13435 mono_error_assert_ok (&error);
13436 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13437 if (!is_ok (&error))
13441 mono_domain_unlock (domain);
13442 mono_loader_unlock ();
13444 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13445 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13446 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13447 goto failure_unlocked;
13450 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13451 if (!is_ok (&error))
13452 goto failure_unlocked;
13454 g_assert (res != (MonoReflectionType*)tb);
13459 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13460 klass->wastypebuilder = TRUE;
13461 mono_domain_unlock (domain);
13462 mono_loader_unlock ();
13464 mono_error_set_pending_exception (&error);
13469 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13471 MonoGenericParamFull *param;
13475 mono_error_init (error);
13477 image = &gparam->tbuilder->module->dynamic_image->image;
13479 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13481 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13482 mono_error_assert_ok (error);
13483 param->param.num = gparam->index;
13485 if (gparam->mbuilder) {
13486 if (!gparam->mbuilder->generic_container) {
13487 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13488 return_val_if_nok (error, FALSE);
13490 MonoClass *klass = mono_class_from_mono_type (tb);
13491 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13492 gparam->mbuilder->generic_container->is_method = TRUE;
13494 * Cannot set owner.method, since the MonoMethod is not created yet.
13495 * Set the image field instead, so type_in_image () works.
13497 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13498 gparam->mbuilder->generic_container->owner.image = klass->image;
13500 param->param.owner = gparam->mbuilder->generic_container;
13501 } else if (gparam->tbuilder) {
13502 if (!gparam->tbuilder->generic_container) {
13503 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13504 return_val_if_nok (error, FALSE);
13505 MonoClass *klass = mono_class_from_mono_type (tb);
13506 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13507 gparam->tbuilder->generic_container->owner.klass = klass;
13509 param->param.owner = gparam->tbuilder->generic_container;
13512 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13514 gparam->type.type = &pklass->byval_arg;
13516 mono_class_set_ref_info (pklass, gparam);
13517 mono_image_append_class_to_reflection_info_set (pklass);
13523 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13526 (void) reflection_initialize_generic_parameter (gparam, &error);
13527 mono_error_set_pending_exception (&error);
13532 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13534 MonoReflectionModuleBuilder *module = sig->module;
13535 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13536 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13541 mono_error_init (error);
13543 check_array_for_usertypes (sig->arguments, error);
13544 return_val_if_nok (error, NULL);
13546 sigbuffer_init (&buf, 32);
13548 sigbuffer_add_value (&buf, 0x07);
13549 sigbuffer_add_value (&buf, na);
13550 if (assembly != NULL){
13551 for (i = 0; i < na; ++i) {
13552 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13553 encode_reflection_type (assembly, type, &buf, error);
13554 if (!is_ok (error)) goto fail;
13558 buflen = buf.p - buf.buf;
13559 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13560 if (!is_ok (error)) goto fail;
13561 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13562 sigbuffer_free (&buf);
13565 sigbuffer_free (&buf);
13570 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13573 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13574 mono_error_set_pending_exception (&error);
13579 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13581 MonoDynamicImage *assembly = sig->module->dynamic_image;
13582 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13587 mono_error_init (error);
13589 check_array_for_usertypes (sig->arguments, error);
13590 return_val_if_nok (error, NULL);
13592 sigbuffer_init (&buf, 32);
13594 sigbuffer_add_value (&buf, 0x06);
13595 for (i = 0; i < na; ++i) {
13596 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13597 encode_reflection_type (assembly, type, &buf, error);
13598 if (!is_ok (error))
13602 buflen = buf.p - buf.buf;
13603 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13604 if (!is_ok (error)) goto fail;
13605 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13606 sigbuffer_free (&buf);
13610 sigbuffer_free (&buf);
13615 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13618 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13619 mono_error_set_pending_exception (&error);
13624 MonoMethod *handle;
13625 MonoDomain *domain;
13626 } DynamicMethodReleaseData;
13629 * The runtime automatically clean up those after finalization.
13631 static MonoReferenceQueue *dynamic_method_queue;
13634 free_dynamic_method (void *dynamic_method)
13636 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13637 MonoDomain *domain = data->domain;
13638 MonoMethod *method = data->handle;
13641 mono_domain_lock (domain);
13642 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13643 g_hash_table_remove (domain->method_to_dyn_method, method);
13644 mono_domain_unlock (domain);
13645 g_assert (dis_link);
13646 mono_gchandle_free (dis_link);
13648 mono_runtime_free_method (domain, method);
13653 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13655 MonoReferenceQueue *queue;
13656 MonoMethod *handle;
13657 DynamicMethodReleaseData *release_data;
13658 ReflectionMethodBuilder rmb;
13659 MonoMethodSignature *sig;
13661 MonoDomain *domain;
13665 mono_error_init (error);
13667 if (mono_runtime_is_shutting_down ()) {
13668 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13672 if (!(queue = dynamic_method_queue)) {
13673 mono_loader_lock ();
13674 if (!(queue = dynamic_method_queue))
13675 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13676 mono_loader_unlock ();
13679 sig = dynamic_method_to_signature (mb, error);
13680 return_val_if_nok (error, FALSE);
13682 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13685 * Resolve references.
13688 * Every second entry in the refs array is reserved for storing handle_class,
13689 * which is needed by the ldtoken implementation in the JIT.
13691 rmb.nrefs = mb->nrefs;
13692 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13693 for (i = 0; i < mb->nrefs; i += 2) {
13694 MonoClass *handle_class;
13696 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13698 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13699 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13701 * The referenced DynamicMethod should already be created by the managed
13702 * code, except in the case of circular references. In that case, we store
13703 * method in the refs array, and fix it up later when the referenced
13704 * DynamicMethod is created.
13706 if (method->mhandle) {
13707 ref = method->mhandle;
13709 /* FIXME: GC object stored in unmanaged memory */
13712 /* FIXME: GC object stored in unmanaged memory */
13713 method->referenced_by = g_slist_append (method->referenced_by, mb);
13715 handle_class = mono_defaults.methodhandle_class;
13717 MonoException *ex = NULL;
13718 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13719 if (!is_ok (error)) {
13724 ex = mono_get_exception_type_load (NULL, NULL);
13725 else if (mono_security_core_clr_enabled ())
13726 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13730 mono_error_set_exception_instance (error, ex);
13735 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13736 rmb.refs [i + 1] = handle_class;
13740 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13741 if (!is_ok (error)) {
13745 klass = mono_class_from_mono_type (owner_type);
13747 klass = mono_defaults.object_class;
13750 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13752 return_val_if_nok (error, FALSE);
13754 release_data = g_new (DynamicMethodReleaseData, 1);
13755 release_data->handle = handle;
13756 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13757 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13758 g_free (release_data);
13760 /* Fix up refs entries pointing at us */
13761 for (l = mb->referenced_by; l; l = l->next) {
13762 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13763 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13766 g_assert (method->mhandle);
13768 data = (gpointer*)wrapper->method_data;
13769 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13770 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13771 data [i + 1] = mb->mhandle;
13774 g_slist_free (mb->referenced_by);
13776 /* ilgen is no longer needed */
13779 domain = mono_domain_get ();
13780 mono_domain_lock (domain);
13781 if (!domain->method_to_dyn_method)
13782 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13783 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13784 mono_domain_unlock (domain);
13790 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13793 (void) reflection_create_dynamic_method (mb, &error);
13794 mono_error_set_pending_exception (&error);
13797 #endif /* DISABLE_REFLECTION_EMIT */
13801 * mono_reflection_is_valid_dynamic_token:
13803 * Returns TRUE if token is valid.
13807 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13809 return lookup_dyn_token (image, token) != NULL;
13812 MonoMethodSignature *
13813 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13815 MonoMethodSignature *sig;
13816 g_assert (image_is_dynamic (image));
13818 mono_error_init (error);
13820 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13824 return mono_method_signature_checked (method, error);
13827 #ifndef DISABLE_REFLECTION_EMIT
13830 * mono_reflection_lookup_dynamic_token:
13832 * Finish the Builder object pointed to by TOKEN and return the corresponding
13833 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13834 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13837 * LOCKING: Take the loader lock
13840 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13842 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13846 mono_error_init (error);
13848 obj = lookup_dyn_token (assembly, token);
13851 g_error ("Could not find required dynamic token 0x%08x", token);
13853 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13859 handle_class = &klass;
13860 gpointer result = resolve_object (image, obj, handle_class, context, error);
13865 * ensure_complete_type:
13867 * Ensure that KLASS is completed if it is a dynamic type, or references
13871 ensure_complete_type (MonoClass *klass, MonoError *error)
13873 mono_error_init (error);
13875 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13876 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13878 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13879 return_if_nok (error);
13881 // Asserting here could break a lot of code
13882 //g_assert (klass->wastypebuilder);
13885 if (klass->generic_class) {
13886 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13889 for (i = 0; i < inst->type_argc; ++i) {
13890 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13891 return_if_nok (error);
13897 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13899 gpointer result = NULL;
13901 mono_error_init (error);
13903 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13904 result = mono_string_intern_checked ((MonoString*)obj, error);
13905 return_val_if_nok (error, NULL);
13906 *handle_class = mono_defaults.string_class;
13908 } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13909 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13910 return_val_if_nok (error, NULL);
13911 MonoClass *mc = mono_class_from_mono_type (type);
13912 if (!mono_class_init (mc)) {
13913 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13918 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13919 return_val_if_nok (error, NULL);
13921 result = mono_class_from_mono_type (inflated);
13922 mono_metadata_free_type (inflated);
13924 result = mono_class_from_mono_type (type);
13926 *handle_class = mono_defaults.typehandle_class;
13928 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13929 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13930 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13931 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13932 result = ((MonoReflectionMethod*)obj)->method;
13934 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13935 mono_error_assert_ok (error);
13937 *handle_class = mono_defaults.methodhandle_class;
13939 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13940 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13941 result = mb->mhandle;
13943 /* Type is not yet created */
13944 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13946 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13947 return_val_if_nok (error, NULL);
13950 * Hopefully this has been filled in by calling CreateType() on the
13954 * TODO: This won't work if the application finishes another
13955 * TypeBuilder instance instead of this one.
13957 result = mb->mhandle;
13960 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13961 mono_error_assert_ok (error);
13963 *handle_class = mono_defaults.methodhandle_class;
13964 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13965 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13967 result = cb->mhandle;
13969 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13971 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13972 return_val_if_nok (error, NULL);
13973 result = cb->mhandle;
13976 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13977 mono_error_assert_ok (error);
13979 *handle_class = mono_defaults.methodhandle_class;
13980 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13981 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13983 ensure_complete_type (field->parent, error);
13984 return_val_if_nok (error, NULL);
13987 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13988 return_val_if_nok (error, NULL);
13990 MonoClass *klass = mono_class_from_mono_type (inflated);
13991 MonoClassField *inflated_field;
13992 gpointer iter = NULL;
13993 mono_metadata_free_type (inflated);
13994 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13995 if (!strcmp (field->name, inflated_field->name))
13998 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13999 result = inflated_field;
14003 *handle_class = mono_defaults.fieldhandle_class;
14005 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14006 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14007 result = fb->handle;
14010 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14012 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14013 return_val_if_nok (error, NULL);
14014 result = fb->handle;
14017 if (fb->handle && fb->handle->parent->generic_container) {
14018 MonoClass *klass = fb->handle->parent;
14019 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14020 return_val_if_nok (error, NULL);
14022 MonoClass *inflated = mono_class_from_mono_type (type);
14024 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14026 mono_metadata_free_type (type);
14028 *handle_class = mono_defaults.fieldhandle_class;
14029 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14030 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14031 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14032 return_val_if_nok (error, NULL);
14035 klass = type->data.klass;
14036 if (klass->wastypebuilder) {
14037 /* Already created */
14041 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14042 return_val_if_nok (error, NULL);
14043 result = type->data.klass;
14046 *handle_class = mono_defaults.typehandle_class;
14047 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14048 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14049 MonoMethodSignature *sig;
14052 if (helper->arguments)
14053 nargs = mono_array_length (helper->arguments);
14057 sig = mono_metadata_signature_alloc (image, nargs);
14058 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14059 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14061 if (helper->unmanaged_call_conv) { /* unmanaged */
14062 sig->call_convention = helper->unmanaged_call_conv - 1;
14063 sig->pinvoke = TRUE;
14064 } else if (helper->call_conv & 0x02) {
14065 sig->call_convention = MONO_CALL_VARARG;
14067 sig->call_convention = MONO_CALL_DEFAULT;
14070 sig->param_count = nargs;
14071 /* TODO: Copy type ? */
14072 sig->ret = helper->return_type->type;
14073 for (i = 0; i < nargs; ++i) {
14074 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14075 if (!is_ok (error)) {
14076 image_g_free (image, sig);
14082 *handle_class = NULL;
14083 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14084 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14085 /* Already created by the managed code */
14086 g_assert (method->mhandle);
14087 result = method->mhandle;
14088 *handle_class = mono_defaults.methodhandle_class;
14089 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14090 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14091 return_val_if_nok (error, NULL);
14092 type = mono_class_inflate_generic_type_checked (type, context, error);
14093 return_val_if_nok (error, NULL);
14095 result = mono_class_from_mono_type (type);
14096 *handle_class = mono_defaults.typehandle_class;
14098 mono_metadata_free_type (type);
14099 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14100 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14101 return_val_if_nok (error, NULL);
14102 type = mono_class_inflate_generic_type_checked (type, context, error);
14103 return_val_if_nok (error, NULL);
14105 result = mono_class_from_mono_type (type);
14106 *handle_class = mono_defaults.typehandle_class;
14108 mono_metadata_free_type (type);
14109 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14110 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14111 MonoClass *inflated;
14113 MonoClassField *field;
14115 if (is_sre_field_builder (mono_object_class (f->fb)))
14116 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14117 else if (is_sr_mono_field (mono_object_class (f->fb)))
14118 field = ((MonoReflectionField*)f->fb)->field;
14120 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)));
14122 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14123 return_val_if_nok (error, NULL);
14124 type = mono_class_inflate_generic_type_checked (finst, context, error);
14125 return_val_if_nok (error, NULL);
14127 inflated = mono_class_from_mono_type (type);
14129 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14130 ensure_complete_type (field->parent, error);
14131 if (!is_ok (error)) {
14132 mono_metadata_free_type (type);
14137 mono_metadata_free_type (type);
14138 *handle_class = mono_defaults.fieldhandle_class;
14139 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14140 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14141 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14142 return_val_if_nok (error, NULL);
14143 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14144 return_val_if_nok (error, NULL);
14146 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14147 MonoMethod *method;
14149 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14150 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14151 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14152 method = ((MonoReflectionMethod *)c->cb)->method;
14154 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)));
14156 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14157 *handle_class = mono_defaults.methodhandle_class;
14158 mono_metadata_free_type (type);
14159 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14160 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14161 if (m->method_args) {
14162 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14163 return_val_if_nok (error, NULL);
14165 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14166 mono_error_assert_ok (error);
14169 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14170 return_val_if_nok (error, NULL);
14171 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14172 return_val_if_nok (error, NULL);
14174 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14175 MonoMethod *method;
14177 if (is_sre_method_builder (mono_object_class (m->mb)))
14178 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14179 else if (is_sr_mono_method (mono_object_class (m->mb)))
14180 method = ((MonoReflectionMethod *)m->mb)->method;
14182 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)));
14184 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14185 mono_metadata_free_type (type);
14187 *handle_class = mono_defaults.methodhandle_class;
14188 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14189 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14192 MonoMethod *method;
14196 mtype = mono_reflection_type_get_handle (m->parent, error);
14197 return_val_if_nok (error, NULL);
14198 klass = mono_class_from_mono_type (mtype);
14200 /* Find the method */
14202 name = mono_string_to_utf8_checked (m->name, error);
14203 return_val_if_nok (error, NULL);
14205 while ((method = mono_class_get_methods (klass, &iter))) {
14206 if (!strcmp (method->name, name))
14213 // FIXME: Check parameters/return value etc. match
14216 *handle_class = mono_defaults.methodhandle_class;
14217 } else if (is_sre_array (mono_object_get_class(obj)) ||
14218 is_sre_byref (mono_object_get_class(obj)) ||
14219 is_sre_pointer (mono_object_get_class(obj))) {
14220 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14221 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14222 return_val_if_nok (error, NULL);
14225 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14226 return_val_if_nok (error, NULL);
14228 result = mono_class_from_mono_type (inflated);
14229 mono_metadata_free_type (inflated);
14231 result = mono_class_from_mono_type (type);
14233 *handle_class = mono_defaults.typehandle_class;
14235 g_print ("%s\n", obj->vtable->klass->name);
14236 g_assert_not_reached ();
14241 #else /* DISABLE_REFLECTION_EMIT */
14244 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14246 g_assert_not_reached ();
14251 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14253 g_assert_not_reached ();
14257 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14259 g_assert_not_reached ();
14263 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14265 g_assert_not_reached ();
14270 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14272 g_assert_not_reached ();
14276 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14278 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14282 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14284 g_assert_not_reached ();
14288 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14290 g_assert_not_reached ();
14293 MonoReflectionModule *
14294 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14296 g_assert_not_reached ();
14301 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14303 g_assert_not_reached ();
14308 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14310 g_assert_not_reached ();
14315 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14316 gboolean create_open_instance, gboolean register_token, MonoError *error)
14318 g_assert_not_reached ();
14323 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14328 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14330 g_assert_not_reached ();
14334 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14336 mono_error_init (error);
14338 *num_overrides = 0;
14341 MonoReflectionEvent *
14342 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14344 g_assert_not_reached ();
14348 MonoReflectionType*
14349 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14351 g_assert_not_reached ();
14356 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14358 g_assert_not_reached ();
14362 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14364 g_assert_not_reached ();
14369 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14371 g_assert_not_reached ();
14376 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14381 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14383 mono_error_init (error);
14388 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14390 mono_error_init (error);
14397 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14399 g_assert_not_reached ();
14402 #endif /* DISABLE_REFLECTION_EMIT */
14404 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14405 const static guint32 declsec_flags_map[] = {
14406 0x00000000, /* empty */
14407 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14408 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14409 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14410 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14411 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14412 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14413 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14414 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14415 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14416 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14417 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14418 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14419 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14420 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14421 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14422 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14423 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14424 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14428 * Returns flags that includes all available security action associated to the handle.
14429 * @token: metadata token (either for a class or a method)
14430 * @image: image where resides the metadata.
14433 mono_declsec_get_flags (MonoImage *image, guint32 token)
14435 int index = mono_metadata_declsec_from_index (image, token);
14436 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14437 guint32 result = 0;
14441 /* HasSecurity can be present for other, not specially encoded, attributes,
14442 e.g. SuppressUnmanagedCodeSecurityAttribute */
14446 for (i = index; i < t->rows; i++) {
14447 guint32 cols [MONO_DECL_SECURITY_SIZE];
14449 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14450 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14453 action = cols [MONO_DECL_SECURITY_ACTION];
14454 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14455 result |= declsec_flags_map [action];
14457 g_assert_not_reached ();
14464 * Get the security actions (in the form of flags) associated with the specified method.
14466 * @method: The method for which we want the declarative security flags.
14467 * Return the declarative security flags for the method (only).
14469 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14470 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14473 mono_declsec_flags_from_method (MonoMethod *method)
14475 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14476 /* FIXME: No cache (for the moment) */
14477 guint32 idx = mono_method_get_index (method);
14478 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14479 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14480 return mono_declsec_get_flags (method->klass->image, idx);
14486 * Get the security actions (in the form of flags) associated with the specified class.
14488 * @klass: The class for which we want the declarative security flags.
14489 * Return the declarative security flags for the class.
14491 * Note: We cache the flags inside the MonoClass structure as this will get
14492 * called very often (at least for each method).
14495 mono_declsec_flags_from_class (MonoClass *klass)
14497 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14498 if (!klass->ext || !klass->ext->declsec_flags) {
14501 idx = mono_metadata_token_index (klass->type_token);
14502 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14503 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14504 mono_loader_lock ();
14505 mono_class_alloc_ext (klass);
14506 mono_loader_unlock ();
14507 /* we cache the flags on classes */
14508 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14510 return klass->ext->declsec_flags;
14516 * Get the security actions (in the form of flags) associated with the specified assembly.
14518 * @assembly: The assembly for which we want the declarative security flags.
14519 * Return the declarative security flags for the assembly.
14522 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14524 guint32 idx = 1; /* there is only one assembly */
14525 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14526 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14527 return mono_declsec_get_flags (assembly->image, idx);
14532 * Fill actions for the specific index (which may either be an encoded class token or
14533 * an encoded method token) from the metadata image.
14534 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14537 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14538 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14540 MonoBoolean result = FALSE;
14542 guint32 cols [MONO_DECL_SECURITY_SIZE];
14543 int index = mono_metadata_declsec_from_index (image, token);
14546 t = &image->tables [MONO_TABLE_DECLSECURITY];
14547 for (i = index; i < t->rows; i++) {
14548 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14550 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14553 /* if present only replace (class) permissions with method permissions */
14554 /* if empty accept either class or method permissions */
14555 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14556 if (!actions->demand.blob) {
14557 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14558 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14559 actions->demand.blob = (char*) (blob + 2);
14560 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14563 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14564 if (!actions->noncasdemand.blob) {
14565 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14566 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14567 actions->noncasdemand.blob = (char*) (blob + 2);
14568 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14571 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14572 if (!actions->demandchoice.blob) {
14573 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14574 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14575 actions->demandchoice.blob = (char*) (blob + 2);
14576 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14586 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14587 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14589 guint32 idx = mono_metadata_token_index (klass->type_token);
14590 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14591 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14592 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14596 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14597 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14599 guint32 idx = mono_method_get_index (method);
14600 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14601 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14602 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14606 * Collect all actions (that requires to generate code in mini) assigned for
14607 * the specified method.
14608 * Note: Don't use the content of actions if the function return FALSE.
14611 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14613 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14614 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14615 MonoBoolean result = FALSE;
14618 /* quick exit if no declarative security is present in the metadata */
14619 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14622 /* we want the original as the wrapper is "free" of the security informations */
14623 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14624 method = mono_marshal_method_from_wrapper (method);
14629 /* First we look for method-level attributes */
14630 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14631 mono_class_init (method->klass);
14632 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14634 result = mono_declsec_get_method_demands_params (method, demands,
14635 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14638 /* Here we use (or create) the class declarative cache to look for demands */
14639 flags = mono_declsec_flags_from_class (method->klass);
14640 if (flags & mask) {
14642 mono_class_init (method->klass);
14643 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14645 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14646 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14649 /* The boolean return value is used as a shortcut in case nothing needs to
14650 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14656 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14658 * Note: Don't use the content of actions if the function return FALSE.
14661 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14663 MonoBoolean result = FALSE;
14666 /* quick exit if no declarative security is present in the metadata */
14667 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14670 /* we want the original as the wrapper is "free" of the security informations */
14671 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14672 method = mono_marshal_method_from_wrapper (method);
14677 /* results are independant - zeroize both */
14678 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14679 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14681 /* First we look for method-level attributes */
14682 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14683 mono_class_init (method->klass);
14685 result = mono_declsec_get_method_demands_params (method, cmethod,
14686 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14689 /* Here we use (or create) the class declarative cache to look for demands */
14690 flags = mono_declsec_flags_from_class (method->klass);
14691 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14692 mono_class_init (method->klass);
14694 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14695 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14702 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14704 * @klass The inherited class - this is the class that provides the security check (attributes)
14706 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14708 * Note: Don't use the content of actions if the function return FALSE.
14711 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14713 MonoBoolean result = FALSE;
14716 /* quick exit if no declarative security is present in the metadata */
14717 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14720 /* Here we use (or create) the class declarative cache to look for demands */
14721 flags = mono_declsec_flags_from_class (klass);
14722 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14723 mono_class_init (klass);
14724 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14726 result |= mono_declsec_get_class_demands_params (klass, demands,
14727 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14734 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14736 * Note: Don't use the content of actions if the function return FALSE.
14739 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14741 /* quick exit if no declarative security is present in the metadata */
14742 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14745 /* we want the original as the wrapper is "free" of the security informations */
14746 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14747 method = mono_marshal_method_from_wrapper (method);
14752 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14753 mono_class_init (method->klass);
14754 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14756 return mono_declsec_get_method_demands_params (method, demands,
14757 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14764 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14766 guint32 cols [MONO_DECL_SECURITY_SIZE];
14770 int index = mono_metadata_declsec_from_index (image, token);
14774 t = &image->tables [MONO_TABLE_DECLSECURITY];
14775 for (i = index; i < t->rows; i++) {
14776 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14778 /* shortcut - index are ordered */
14779 if (token != cols [MONO_DECL_SECURITY_PARENT])
14782 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14783 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14784 entry->blob = (char*) (metadata + 2);
14785 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14794 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14796 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14797 guint32 idx = mono_method_get_index (method);
14798 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14799 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14800 return get_declsec_action (method->klass->image, idx, action, entry);
14806 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14809 guint32 flags = mono_declsec_flags_from_class (klass);
14810 if (declsec_flags_map [action] & flags) {
14811 guint32 idx = mono_metadata_token_index (klass->type_token);
14812 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14813 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14814 return get_declsec_action (klass->image, idx, action, entry);
14820 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14822 guint32 idx = 1; /* there is only one assembly */
14823 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14824 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14826 return get_declsec_action (assembly->image, idx, action, entry);
14830 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14832 MonoObject *res, *exc;
14834 static MonoMethod *method = NULL;
14836 mono_error_init (error);
14838 if (method == NULL) {
14839 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14844 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14845 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14847 g_assert (mono_class_get_ref_info (klass));
14848 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14850 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14851 return_val_if_nok (error, FALSE);
14853 MonoError inner_error;
14854 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14856 if (exc || !is_ok (&inner_error)) {
14857 mono_error_cleanup (&inner_error);
14860 return *(MonoBoolean*)mono_object_unbox (res);
14864 * mono_reflection_type_get_type:
14865 * @reftype: the System.Type object
14867 * Returns the MonoType* associated with the C# System.Type object @reftype.
14870 mono_reflection_type_get_type (MonoReflectionType *reftype)
14872 g_assert (reftype);
14875 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14876 mono_error_assert_ok (&error);
14881 * mono_reflection_assembly_get_assembly:
14882 * @refassembly: the System.Reflection.Assembly object
14884 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14887 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14889 g_assert (refassembly);
14891 return refassembly->assembly;