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);
200 #define RESOLVE_TYPE(type, error) do { \
201 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
204 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205 __type = mono_reflection_type_resolve_user_types (__type, error); \
206 if (mono_error_ok (error)) \
207 mono_array_set (arr, MonoReflectionType*, index, __type); \
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
250 dynamic_images_lock (void)
252 mono_os_mutex_lock (&dynamic_images_mutex);
256 dynamic_images_unlock (void)
258 mono_os_mutex_unlock (&dynamic_images_mutex);
262 * mono_find_dynamic_image_owner:
264 * Find the dynamic image, if any, which a given pointer is located in the memory of.
267 mono_find_dynamic_image_owner (void *ptr)
269 MonoImage *owner = NULL;
272 dynamic_images_lock ();
276 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278 if (mono_mempool_contains_addr (image->mempool, ptr))
283 dynamic_images_unlock ();
289 mono_reflection_init (void)
291 mono_os_mutex_init (&dynamic_images_mutex);
295 dynamic_image_lock (MonoDynamicImage *image)
297 MONO_PREPARE_BLOCKING;
298 mono_image_lock ((MonoImage*)image);
299 MONO_FINISH_BLOCKING;
303 dynamic_image_unlock (MonoDynamicImage *image)
305 mono_image_unlock ((MonoImage*)image);
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
311 MONO_REQ_GC_UNSAFE_MODE;
313 dynamic_image_lock (assembly);
314 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315 dynamic_image_unlock (assembly);
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
321 MONO_REQ_GC_UNSAFE_MODE;
325 dynamic_image_lock (assembly);
326 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327 dynamic_image_unlock (assembly);
333 sigbuffer_init (SigBuffer *buf, int size)
335 MONO_REQ_GC_NEUTRAL_MODE;
337 buf->buf = (char *)g_malloc (size);
339 buf->end = buf->buf + size;
343 sigbuffer_make_room (SigBuffer *buf, int size)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 if (buf->end - buf->p < size) {
348 int new_size = buf->end - buf->buf + size + 32;
349 char *p = (char *)g_realloc (buf->buf, new_size);
350 size = buf->p - buf->buf;
353 buf->end = buf->buf + new_size;
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
360 MONO_REQ_GC_NEUTRAL_MODE;
362 sigbuffer_make_room (buf, 6);
363 mono_metadata_encode_value (val, buf->p, &buf->p);
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
369 MONO_REQ_GC_NEUTRAL_MODE;
371 sigbuffer_make_room (buf, 1);
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
379 MONO_REQ_GC_NEUTRAL_MODE;
381 sigbuffer_make_room (buf, size);
382 memcpy (buf->p, p, size);
387 sigbuffer_free (SigBuffer *buf)
389 MONO_REQ_GC_NEUTRAL_MODE;
394 #ifndef DISABLE_REFLECTION_EMIT
398 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
402 image_g_malloc (MonoImage *image, guint size)
404 MONO_REQ_GC_NEUTRAL_MODE;
407 return mono_image_alloc (image, size);
409 return g_malloc (size);
411 #endif /* !DISABLE_REFLECTION_EMIT */
416 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
420 image_g_malloc0 (MonoImage *image, guint size)
422 MONO_REQ_GC_NEUTRAL_MODE;
425 return mono_image_alloc0 (image, size);
427 return g_malloc0 (size);
432 * @image: a MonoImage
435 * If @image is NULL, free @ptr, otherwise do nothing.
438 image_g_free (MonoImage *image, gpointer ptr)
444 #ifndef DISABLE_REFLECTION_EMIT
446 image_strdup (MonoImage *image, const char *s)
448 MONO_REQ_GC_NEUTRAL_MODE;
451 return mono_image_strdup (image, s);
457 #define image_g_new(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
460 #define image_g_new0(image,struct_type, n_structs) \
461 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
465 alloc_table (MonoDynamicTable *table, guint nrows)
467 MONO_REQ_GC_NEUTRAL_MODE;
470 g_assert (table->columns);
471 if (nrows + 1 >= table->alloc_rows) {
472 while (nrows + 1 >= table->alloc_rows) {
473 if (table->alloc_rows == 0)
474 table->alloc_rows = 16;
476 table->alloc_rows *= 2;
479 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
484 make_room_in_stream (MonoDynamicStream *stream, int size)
486 MONO_REQ_GC_NEUTRAL_MODE;
488 if (size <= stream->alloc_size)
491 while (stream->alloc_size <= size) {
492 if (stream->alloc_size < 4096)
493 stream->alloc_size = 4096;
495 stream->alloc_size *= 2;
498 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
504 MONO_REQ_GC_NEUTRAL_MODE;
508 gpointer oldkey, oldval;
510 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511 return GPOINTER_TO_UINT (oldval);
513 len = strlen (str) + 1;
516 make_room_in_stream (sh, idx + len);
519 * We strdup the string even if we already copy them in sh->data
520 * so that the string pointers in the hash remain valid even if
521 * we need to realloc sh->data. We may want to avoid that later.
523 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524 memcpy (sh->data + idx, str, len);
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
532 MONO_REQ_GC_UNSAFE_MODE;
534 char *name = mono_string_to_utf8 (str);
536 idx = string_heap_insert (sh, name);
541 #ifndef DISABLE_REFLECTION_EMIT
543 string_heap_init (MonoDynamicStream *sh)
545 MONO_REQ_GC_NEUTRAL_MODE;
548 sh->alloc_size = 4096;
549 sh->data = (char *)g_malloc (4096);
550 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
551 string_heap_insert (sh, "");
556 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
558 MONO_REQ_GC_NEUTRAL_MODE;
562 make_room_in_stream (stream, stream->index + len);
563 memcpy (stream->data + stream->index, data, len);
565 stream->index += len;
567 * align index? Not without adding an additional param that controls it since
568 * we may store a blob value in pieces.
574 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
576 MONO_REQ_GC_NEUTRAL_MODE;
580 make_room_in_stream (stream, stream->index + len);
581 memset (stream->data + stream->index, 0, len);
583 stream->index += len;
588 stream_data_align (MonoDynamicStream *stream)
590 MONO_REQ_GC_NEUTRAL_MODE;
593 guint32 count = stream->index % 4;
595 /* we assume the stream data will be aligned */
597 mono_image_add_stream_data (stream, buf, 4 - count);
600 #ifndef DISABLE_REFLECTION_EMIT
602 mono_blob_entry_hash (const char* str)
604 MONO_REQ_GC_NEUTRAL_MODE;
608 len = mono_metadata_decode_blob_size (str, &str);
612 for (str += 1; str < end; str++)
613 h = (h << 5) - h + *str;
621 mono_blob_entry_equal (const char *str1, const char *str2) {
622 MONO_REQ_GC_NEUTRAL_MODE;
627 len = mono_metadata_decode_blob_size (str1, &end1);
628 len2 = mono_metadata_decode_blob_size (str2, &end2);
631 return memcmp (end1, end2, len) == 0;
635 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
637 MONO_REQ_GC_NEUTRAL_MODE;
641 gpointer oldkey, oldval;
643 copy = (char *)g_malloc (s1+s2);
644 memcpy (copy, b1, s1);
645 memcpy (copy + s1, b2, s2);
646 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
648 idx = GPOINTER_TO_UINT (oldval);
650 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
651 mono_image_add_stream_data (&assembly->blob, b2, s2);
652 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
658 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
660 MONO_REQ_GC_NEUTRAL_MODE;
664 guint32 size = buf->p - buf->buf;
666 g_assert (size <= (buf->end - buf->buf));
667 mono_metadata_encode_value (size, b, &b);
668 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
672 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
673 * dest may be misaligned.
676 swap_with_size (char *dest, const char* val, int len, int nelem) {
677 MONO_REQ_GC_NEUTRAL_MODE;
678 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
681 for (elem = 0; elem < nelem; ++elem) {
707 g_assert_not_reached ();
713 memcpy (dest, val, len * nelem);
718 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
720 MONO_REQ_GC_UNSAFE_MODE;
724 guint32 idx = 0, len;
726 len = str->length * 2;
727 mono_metadata_encode_value (len, b, &b);
728 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
730 char *swapped = g_malloc (2 * mono_string_length (str));
731 const char *p = (const char*)mono_string_chars (str);
733 swap_with_size (swapped, p, 2, mono_string_length (str));
734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
743 #ifndef DISABLE_REFLECTION_EMIT
745 default_class_from_mono_type (MonoType *type)
747 MONO_REQ_GC_NEUTRAL_MODE;
749 switch (type->type) {
750 case MONO_TYPE_OBJECT:
751 return mono_defaults.object_class;
753 return mono_defaults.void_class;
754 case MONO_TYPE_BOOLEAN:
755 return mono_defaults.boolean_class;
757 return mono_defaults.char_class;
759 return mono_defaults.sbyte_class;
761 return mono_defaults.byte_class;
763 return mono_defaults.int16_class;
765 return mono_defaults.uint16_class;
767 return mono_defaults.int32_class;
769 return mono_defaults.uint32_class;
771 return mono_defaults.int_class;
773 return mono_defaults.uint_class;
775 return mono_defaults.int64_class;
777 return mono_defaults.uint64_class;
779 return mono_defaults.single_class;
781 return mono_defaults.double_class;
782 case MONO_TYPE_STRING:
783 return mono_defaults.string_class;
785 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
786 g_assert_not_reached ();
794 * mono_class_get_ref_info:
796 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
799 mono_class_get_ref_info (MonoClass *klass)
801 MONO_REQ_GC_UNSAFE_MODE;
803 if (klass->ref_info_handle == 0)
806 return mono_gchandle_get_target (klass->ref_info_handle);
810 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
812 MONO_REQ_GC_UNSAFE_MODE;
814 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
815 g_assert (klass->ref_info_handle != 0);
819 mono_class_free_ref_info (MonoClass *klass)
821 MONO_REQ_GC_NEUTRAL_MODE;
823 if (klass->ref_info_handle) {
824 mono_gchandle_free (klass->ref_info_handle);
825 klass->ref_info_handle = 0;
830 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
832 MONO_REQ_GC_NEUTRAL_MODE;
835 MonoGenericInst *class_inst;
840 class_inst = gclass->context.class_inst;
842 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
843 klass = gclass->container_class;
844 sigbuffer_add_value (buf, klass->byval_arg.type);
845 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
847 sigbuffer_add_value (buf, class_inst->type_argc);
848 for (i = 0; i < class_inst->type_argc; ++i)
849 encode_type (assembly, class_inst->type_argv [i], buf);
854 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
856 MONO_REQ_GC_NEUTRAL_MODE;
859 g_assert_not_reached ();
864 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
868 case MONO_TYPE_BOOLEAN:
882 case MONO_TYPE_STRING:
883 case MONO_TYPE_OBJECT:
884 case MONO_TYPE_TYPEDBYREF:
885 sigbuffer_add_value (buf, type->type);
888 sigbuffer_add_value (buf, type->type);
889 encode_type (assembly, type->data.type, buf);
891 case MONO_TYPE_SZARRAY:
892 sigbuffer_add_value (buf, type->type);
893 encode_type (assembly, &type->data.klass->byval_arg, buf);
895 case MONO_TYPE_VALUETYPE:
896 case MONO_TYPE_CLASS: {
897 MonoClass *k = mono_class_from_mono_type (type);
899 if (k->generic_container) {
900 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
901 encode_generic_class (assembly, gclass, buf);
904 * Make sure we use the correct type.
906 sigbuffer_add_value (buf, k->byval_arg.type);
908 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
909 * otherwise two typerefs could point to the same type, leading to
910 * verification errors.
912 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
916 case MONO_TYPE_ARRAY:
917 sigbuffer_add_value (buf, type->type);
918 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
919 sigbuffer_add_value (buf, type->data.array->rank);
920 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
921 sigbuffer_add_value (buf, 0);
923 case MONO_TYPE_GENERICINST:
924 encode_generic_class (assembly, type->data.generic_class, buf);
928 sigbuffer_add_value (buf, type->type);
929 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
932 g_error ("need to encode type %x", type->type);
937 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
939 MONO_REQ_GC_UNSAFE_MODE;
941 mono_error_init (error);
944 sigbuffer_add_value (buf, MONO_TYPE_VOID);
948 MonoType *t = mono_reflection_type_get_handle (type, error);
949 return_if_nok (error);
950 encode_type (assembly, t, buf);
954 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
956 MONO_REQ_GC_UNSAFE_MODE;
960 mono_error_init (error);
963 for (i = 0; i < mono_array_length (modreq); ++i) {
964 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
965 return_if_nok (error);
966 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
967 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
971 for (i = 0; i < mono_array_length (modopt); ++i) {
972 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
973 return_if_nok (error);
974 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
975 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
980 #ifndef DISABLE_REFLECTION_EMIT
982 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
984 MONO_REQ_GC_UNSAFE_MODE;
988 guint32 nparams = sig->param_count;
994 sigbuffer_init (&buf, 32);
996 * FIXME: vararg, explicit_this, differenc call_conv values...
998 idx = sig->call_convention;
1000 idx |= 0x20; /* hasthis */
1001 if (sig->generic_param_count)
1002 idx |= 0x10; /* generic */
1003 sigbuffer_add_byte (&buf, idx);
1004 if (sig->generic_param_count)
1005 sigbuffer_add_value (&buf, sig->generic_param_count);
1006 sigbuffer_add_value (&buf, nparams);
1007 encode_type (assembly, sig->ret, &buf);
1008 for (i = 0; i < nparams; ++i) {
1009 if (i == sig->sentinelpos)
1010 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1011 encode_type (assembly, sig->params [i], &buf);
1013 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1014 sigbuffer_free (&buf);
1020 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1022 MONO_REQ_GC_UNSAFE_MODE;
1024 mono_error_init (error);
1027 * FIXME: reuse code from method_encode_signature().
1031 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1032 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1033 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1036 sigbuffer_init (&buf, 32);
1037 /* LAMESPEC: all the call conv spec is foobared */
1038 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1039 if (mb->call_conv & 2)
1040 idx |= 0x5; /* vararg */
1041 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1042 idx |= 0x20; /* hasthis */
1044 idx |= 0x10; /* generic */
1045 sigbuffer_add_byte (&buf, idx);
1047 sigbuffer_add_value (&buf, ngparams);
1048 sigbuffer_add_value (&buf, nparams + notypes);
1049 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1052 encode_reflection_type (assembly, mb->rtype, &buf, error);
1055 for (i = 0; i < nparams; ++i) {
1056 MonoArray *modreq = NULL;
1057 MonoArray *modopt = NULL;
1058 MonoReflectionType *pt;
1060 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1061 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1062 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1063 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1064 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1067 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1068 encode_reflection_type (assembly, pt, &buf, error);
1073 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1074 for (i = 0; i < notypes; ++i) {
1075 MonoReflectionType *pt;
1077 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1078 encode_reflection_type (assembly, pt, &buf, error);
1083 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1085 sigbuffer_free (&buf);
1090 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1092 MONO_REQ_GC_UNSAFE_MODE;
1094 mono_error_init (error);
1096 MonoDynamicTable *table;
1098 guint32 idx, sig_idx;
1099 guint nl = mono_array_length (ilgen->locals);
1103 sigbuffer_init (&buf, 32);
1104 sigbuffer_add_value (&buf, 0x07);
1105 sigbuffer_add_value (&buf, nl);
1106 for (i = 0; i < nl; ++i) {
1107 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1110 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1112 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1113 if (!is_ok (error)) {
1114 sigbuffer_free (&buf);
1118 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1119 sigbuffer_free (&buf);
1121 if (assembly->standalonesig_cache == NULL)
1122 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1123 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1127 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1128 idx = table->next_idx ++;
1130 alloc_table (table, table->rows);
1131 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1133 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1135 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1141 method_count_clauses (MonoReflectionILGen *ilgen)
1143 MONO_REQ_GC_UNSAFE_MODE;
1145 guint32 num_clauses = 0;
1148 MonoILExceptionInfo *ex_info;
1149 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1150 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1151 if (ex_info->handlers)
1152 num_clauses += mono_array_length (ex_info->handlers);
1160 #ifndef DISABLE_REFLECTION_EMIT
1161 static MonoExceptionClause*
1162 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1164 MONO_REQ_GC_UNSAFE_MODE;
1166 mono_error_init (error);
1168 MonoExceptionClause *clauses;
1169 MonoExceptionClause *clause;
1170 MonoILExceptionInfo *ex_info;
1171 MonoILExceptionBlock *ex_block;
1172 guint32 finally_start;
1173 int i, j, clause_index;;
1175 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1178 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1179 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1180 finally_start = ex_info->start + ex_info->len;
1181 if (!ex_info->handlers)
1183 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1184 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1185 clause = &(clauses [clause_index]);
1187 clause->flags = ex_block->type;
1188 clause->try_offset = ex_info->start;
1190 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1191 clause->try_len = finally_start - ex_info->start;
1193 clause->try_len = ex_info->len;
1194 clause->handler_offset = ex_block->start;
1195 clause->handler_len = ex_block->len;
1196 if (ex_block->extype) {
1197 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1199 if (!is_ok (error)) {
1200 image_g_free (image, clauses);
1203 clause->data.catch_class = mono_class_from_mono_type (extype);
1205 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1206 clause->data.filter_offset = ex_block->filter_offset;
1208 clause->data.filter_offset = 0;
1210 finally_start = ex_block->start + ex_block->len;
1218 #endif /* !DISABLE_REFLECTION_EMIT */
1221 * method_encode_code:
1223 * @assembly the assembly
1224 * @mb the managed MethodBuilder
1225 * @error set on error
1227 * Note that the return value is not sensible if @error is set.
1230 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1232 MONO_REQ_GC_UNSAFE_MODE;
1237 gint32 max_stack, i;
1238 gint32 num_locals = 0;
1239 gint32 num_exception = 0;
1242 char fat_header [12];
1244 guint16 short_value;
1245 guint32 local_sig = 0;
1246 guint32 header_size = 12;
1249 mono_error_init (error);
1251 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1252 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1256 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1258 code = mb->ilgen->code;
1259 code_size = mb->ilgen->code_len;
1260 max_stack = mb->ilgen->max_stack;
1261 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1262 if (mb->ilgen->ex_handlers)
1263 num_exception = method_count_clauses (mb->ilgen);
1267 char *name = mono_string_to_utf8 (mb->name);
1268 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1269 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1275 code_size = mono_array_length (code);
1276 max_stack = 8; /* we probably need to run a verifier on the code... */
1279 stream_data_align (&assembly->code);
1281 /* check for exceptions, maxstack, locals */
1282 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1284 if (code_size < 64 && !(code_size & 1)) {
1285 flags = (code_size << 2) | 0x2;
1286 } else if (code_size < 32 && (code_size & 1)) {
1287 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1291 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1292 /* add to the fixup todo list */
1293 if (mb->ilgen && mb->ilgen->num_token_fixups)
1294 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1295 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1296 return assembly->text_rva + idx;
1300 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1301 return_val_if_nok (error, 0);
1304 * FIXME: need to set also the header size in fat_flags.
1305 * (and more sects and init locals flags)
1309 fat_flags |= METHOD_HEADER_MORE_SECTS;
1310 if (mb->init_locals)
1311 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1312 fat_header [0] = fat_flags;
1313 fat_header [1] = (header_size / 4 ) << 4;
1314 short_value = GUINT16_TO_LE (max_stack);
1315 memcpy (fat_header + 2, &short_value, 2);
1316 int_value = GUINT32_TO_LE (code_size);
1317 memcpy (fat_header + 4, &int_value, 4);
1318 int_value = GUINT32_TO_LE (local_sig);
1319 memcpy (fat_header + 8, &int_value, 4);
1320 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1321 /* add to the fixup todo list */
1322 if (mb->ilgen && mb->ilgen->num_token_fixups)
1323 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1325 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1326 if (num_exception) {
1327 unsigned char sheader [4];
1328 MonoILExceptionInfo * ex_info;
1329 MonoILExceptionBlock * ex_block;
1332 stream_data_align (&assembly->code);
1333 /* always use fat format for now */
1334 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1335 num_exception *= 6 * sizeof (guint32);
1336 num_exception += 4; /* include the size of the header */
1337 sheader [1] = num_exception & 0xff;
1338 sheader [2] = (num_exception >> 8) & 0xff;
1339 sheader [3] = (num_exception >> 16) & 0xff;
1340 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1341 /* fat header, so we are already aligned */
1343 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1344 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1345 if (ex_info->handlers) {
1346 int finally_start = ex_info->start + ex_info->len;
1347 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1349 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1351 val = GUINT32_TO_LE (ex_block->type);
1352 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1354 val = GUINT32_TO_LE (ex_info->start);
1355 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1356 /* need fault, too, probably */
1357 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1358 val = GUINT32_TO_LE (finally_start - ex_info->start);
1360 val = GUINT32_TO_LE (ex_info->len);
1361 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362 /* handler offset */
1363 val = GUINT32_TO_LE (ex_block->start);
1364 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1366 val = GUINT32_TO_LE (ex_block->len);
1367 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1368 finally_start = ex_block->start + ex_block->len;
1369 if (ex_block->extype) {
1370 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1371 return_val_if_nok (error, 0);
1373 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1375 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1376 val = ex_block->filter_offset;
1380 val = GUINT32_TO_LE (val);
1381 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1382 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1383 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1386 g_error ("No clauses for ex info block %d", i);
1390 return assembly->text_rva + idx;
1394 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1396 MONO_REQ_GC_NEUTRAL_MODE;
1399 MonoDynamicTable *table;
1402 table = &assembly->tables [table_idx];
1404 g_assert (col < table->columns);
1406 values = table->values + table->columns;
1407 for (i = 1; i <= table->rows; ++i) {
1408 if (values [col] == token)
1410 values += table->columns;
1416 * LOCKING: Acquires the loader lock.
1418 static MonoCustomAttrInfo*
1419 lookup_custom_attr (MonoImage *image, gpointer member)
1421 MONO_REQ_GC_NEUTRAL_MODE;
1423 MonoCustomAttrInfo* res;
1425 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1430 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1436 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1438 MONO_REQ_GC_UNSAFE_MODE;
1440 /* FIXME: Need to do more checks */
1441 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1442 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1444 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1451 static MonoCustomAttrInfo*
1452 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1454 MONO_REQ_GC_UNSAFE_MODE;
1456 int i, index, count, not_visible;
1457 MonoCustomAttrInfo *ainfo;
1458 MonoReflectionCustomAttr *cattr;
1462 /* FIXME: check in assembly the Run flag is set */
1464 count = mono_array_length (cattrs);
1466 /* Skip nonpublic attributes since MS.NET seems to do the same */
1467 /* FIXME: This needs to be done more globally */
1469 for (i = 0; i < count; ++i) {
1470 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471 if (!custom_attr_visible (image, cattr))
1474 count -= not_visible;
1476 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1478 ainfo->image = image;
1479 ainfo->num_attrs = count;
1480 ainfo->cached = alloc_img != NULL;
1482 for (i = 0; i < count; ++i) {
1483 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484 if (custom_attr_visible (image, cattr)) {
1485 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1486 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1487 ainfo->attrs [index].ctor = cattr->ctor->method;
1488 ainfo->attrs [index].data = saved;
1489 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1497 #ifndef DISABLE_REFLECTION_EMIT
1499 * LOCKING: Acquires the loader lock.
1502 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1504 MONO_REQ_GC_UNSAFE_MODE;
1506 MonoCustomAttrInfo *ainfo, *tmp;
1508 if (!cattrs || !mono_array_length (cattrs))
1511 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1513 mono_loader_lock ();
1514 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1516 mono_custom_attrs_free (tmp);
1517 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1518 mono_loader_unlock ();
1524 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1526 MONO_REQ_GC_NEUTRAL_MODE;
1528 if (ainfo && !ainfo->cached)
1533 * idx is the table index of the object
1534 * type is one of MONO_CUSTOM_ATTR_*
1537 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1539 MONO_REQ_GC_UNSAFE_MODE;
1541 MonoDynamicTable *table;
1542 MonoReflectionCustomAttr *cattr;
1544 guint32 count, i, token;
1546 char *p = blob_size;
1548 mono_error_init (error);
1550 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1553 count = mono_array_length (cattrs);
1554 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1555 table->rows += count;
1556 alloc_table (table, table->rows);
1557 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1558 idx <<= MONO_CUSTOM_ATTR_BITS;
1560 for (i = 0; i < count; ++i) {
1561 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1562 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1563 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1564 if (!mono_error_ok (error)) goto fail;
1565 type = mono_metadata_token_index (token);
1566 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1567 switch (mono_metadata_token_table (token)) {
1568 case MONO_TABLE_METHOD:
1569 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1571 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1572 * method, not the one returned by mono_image_create_token ().
1574 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1576 case MONO_TABLE_MEMBERREF:
1577 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1580 g_warning ("got wrong token in custom attr");
1583 values [MONO_CUSTOM_ATTR_TYPE] = type;
1585 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1586 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1587 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1588 values += MONO_CUSTOM_ATTR_SIZE;
1599 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1601 MONO_REQ_GC_UNSAFE_MODE;
1603 MonoDynamicTable *table;
1605 guint32 count, i, idx;
1606 MonoReflectionPermissionSet *perm;
1611 count = mono_array_length (permissions);
1612 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1613 table->rows += count;
1614 alloc_table (table, table->rows);
1616 for (i = 0; i < mono_array_length (permissions); ++i) {
1617 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1619 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1621 idx = mono_metadata_token_index (parent_token);
1622 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1623 switch (mono_metadata_token_table (parent_token)) {
1624 case MONO_TABLE_TYPEDEF:
1625 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1627 case MONO_TABLE_METHOD:
1628 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1630 case MONO_TABLE_ASSEMBLY:
1631 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1634 g_assert_not_reached ();
1637 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1638 values [MONO_DECL_SECURITY_PARENT] = idx;
1639 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1646 * Fill in the MethodDef and ParamDef tables for a method.
1647 * This is used for both normal methods and constructors.
1650 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1652 MONO_REQ_GC_UNSAFE_MODE;
1654 MonoDynamicTable *table;
1658 mono_error_init (error);
1660 /* room in this table is already allocated */
1661 table = &assembly->tables [MONO_TABLE_METHOD];
1662 *mb->table_idx = table->next_idx ++;
1663 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1664 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1665 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1666 values [MONO_METHOD_FLAGS] = mb->attrs;
1667 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1668 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1669 return_val_if_nok (error, FALSE);
1670 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1671 return_val_if_nok (error, FALSE);
1673 table = &assembly->tables [MONO_TABLE_PARAM];
1674 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1676 mono_image_add_decl_security (assembly,
1677 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1680 MonoDynamicTable *mtable;
1683 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1684 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1687 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1688 if (mono_array_get (mb->pinfo, gpointer, i))
1691 table->rows += count;
1692 alloc_table (table, table->rows);
1693 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1694 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1695 MonoReflectionParamBuilder *pb;
1696 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1697 values [MONO_PARAM_FLAGS] = pb->attrs;
1698 values [MONO_PARAM_SEQUENCE] = i;
1699 if (pb->name != NULL) {
1700 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1702 values [MONO_PARAM_NAME] = 0;
1704 values += MONO_PARAM_SIZE;
1705 if (pb->marshal_info) {
1707 alloc_table (mtable, mtable->rows);
1708 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1709 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1710 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1711 return_val_if_nok (error, FALSE);
1713 pb->table_idx = table->next_idx++;
1714 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1715 guint32 field_type = 0;
1716 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1718 alloc_table (mtable, mtable->rows);
1719 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1720 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1721 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1722 mvalues [MONO_CONSTANT_TYPE] = field_type;
1723 mvalues [MONO_CONSTANT_PADDING] = 0;
1732 #ifndef DISABLE_REFLECTION_EMIT
1734 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1736 MONO_REQ_GC_UNSAFE_MODE;
1738 mono_error_init (error);
1739 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1741 rmb->ilgen = mb->ilgen;
1742 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1743 return_val_if_nok (error, FALSE);
1744 rmb->parameters = mb->parameters;
1745 rmb->generic_params = mb->generic_params;
1746 rmb->generic_container = mb->generic_container;
1747 rmb->opt_types = NULL;
1748 rmb->pinfo = mb->pinfo;
1749 rmb->attrs = mb->attrs;
1750 rmb->iattrs = mb->iattrs;
1751 rmb->call_conv = mb->call_conv;
1752 rmb->code = mb->code;
1753 rmb->type = mb->type;
1754 rmb->name = mb->name;
1755 rmb->table_idx = &mb->table_idx;
1756 rmb->init_locals = mb->init_locals;
1757 rmb->skip_visibility = FALSE;
1758 rmb->return_modreq = mb->return_modreq;
1759 rmb->return_modopt = mb->return_modopt;
1760 rmb->param_modreq = mb->param_modreq;
1761 rmb->param_modopt = mb->param_modopt;
1762 rmb->permissions = mb->permissions;
1763 rmb->mhandle = mb->mhandle;
1768 rmb->charset = mb->charset;
1769 rmb->extra_flags = mb->extra_flags;
1770 rmb->native_cc = mb->native_cc;
1771 rmb->dllentry = mb->dllentry;
1779 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1781 MONO_REQ_GC_UNSAFE_MODE;
1783 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1785 mono_error_init (error);
1787 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1789 rmb->ilgen = mb->ilgen;
1790 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1791 return_val_if_nok (error, FALSE);
1792 rmb->parameters = mb->parameters;
1793 rmb->generic_params = NULL;
1794 rmb->generic_container = NULL;
1795 rmb->opt_types = NULL;
1796 rmb->pinfo = mb->pinfo;
1797 rmb->attrs = mb->attrs;
1798 rmb->iattrs = mb->iattrs;
1799 rmb->call_conv = mb->call_conv;
1801 rmb->type = mb->type;
1802 rmb->name = mono_string_new (mono_domain_get (), name);
1803 rmb->table_idx = &mb->table_idx;
1804 rmb->init_locals = mb->init_locals;
1805 rmb->skip_visibility = FALSE;
1806 rmb->return_modreq = NULL;
1807 rmb->return_modopt = NULL;
1808 rmb->param_modreq = mb->param_modreq;
1809 rmb->param_modopt = mb->param_modopt;
1810 rmb->permissions = mb->permissions;
1811 rmb->mhandle = mb->mhandle;
1819 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1821 MONO_REQ_GC_UNSAFE_MODE;
1823 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1825 rmb->ilgen = mb->ilgen;
1826 rmb->rtype = mb->rtype;
1827 rmb->parameters = mb->parameters;
1828 rmb->generic_params = NULL;
1829 rmb->generic_container = NULL;
1830 rmb->opt_types = NULL;
1832 rmb->attrs = mb->attrs;
1834 rmb->call_conv = mb->call_conv;
1836 rmb->type = (MonoObject *) mb->owner;
1837 rmb->name = mb->name;
1838 rmb->table_idx = NULL;
1839 rmb->init_locals = mb->init_locals;
1840 rmb->skip_visibility = mb->skip_visibility;
1841 rmb->return_modreq = NULL;
1842 rmb->return_modopt = NULL;
1843 rmb->param_modreq = NULL;
1844 rmb->param_modopt = NULL;
1845 rmb->permissions = NULL;
1846 rmb->mhandle = mb->mhandle;
1853 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1855 MONO_REQ_GC_UNSAFE_MODE;
1857 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1858 MonoDynamicTable *table;
1861 MonoReflectionMethod *m;
1864 mono_error_init (error);
1866 if (!mb->override_methods)
1869 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1870 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1872 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1874 alloc_table (table, table->rows);
1875 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1876 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1877 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1879 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1880 return_val_if_nok (error, FALSE);
1882 switch (mono_metadata_token_table (tok)) {
1883 case MONO_TABLE_MEMBERREF:
1884 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1886 case MONO_TABLE_METHOD:
1887 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1890 g_assert_not_reached ();
1892 values [MONO_METHODIMPL_DECLARATION] = tok;
1898 #ifndef DISABLE_REFLECTION_EMIT
1900 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1902 MONO_REQ_GC_UNSAFE_MODE;
1904 MonoDynamicTable *table;
1906 ReflectionMethodBuilder rmb;
1909 mono_error_init (error);
1911 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1912 !mono_image_basic_method (&rmb, assembly, error))
1915 mb->table_idx = *rmb.table_idx;
1917 if (mb->dll) { /* It's a P/Invoke method */
1919 /* map CharSet values to on-disk values */
1920 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1921 int extra_flags = mb->extra_flags;
1922 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1924 alloc_table (table, table->rows);
1925 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1927 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1928 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1930 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1932 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1933 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1934 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1935 table = &assembly->tables [MONO_TABLE_MODULEREF];
1937 alloc_table (table, table->rows);
1938 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1939 values [MONO_IMPLMAP_SCOPE] = table->rows;
1943 if (mb->generic_params) {
1944 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1945 table->rows += mono_array_length (mb->generic_params);
1946 alloc_table (table, table->rows);
1947 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1948 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1950 mono_image_get_generic_param_info (
1951 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1959 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1961 MONO_REQ_GC_UNSAFE_MODE;
1963 ReflectionMethodBuilder rmb;
1965 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1968 if (!mono_image_basic_method (&rmb, assembly, error))
1971 mb->table_idx = *rmb.table_idx;
1978 type_get_fully_qualified_name (MonoType *type)
1980 MONO_REQ_GC_NEUTRAL_MODE;
1982 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1986 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1988 MONO_REQ_GC_UNSAFE_MODE;
1993 klass = mono_class_from_mono_type (type);
1995 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1996 ta = klass->image->assembly;
1997 if (assembly_is_dynamic (ta) || (ta == ass)) {
1998 if (klass->generic_class || klass->generic_container)
1999 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2000 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2005 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2008 #ifndef DISABLE_REFLECTION_EMIT
2009 /*field_image is the image to which the eventual custom mods have been encoded against*/
2011 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2013 MONO_REQ_GC_NEUTRAL_MODE;
2016 guint32 idx, i, token;
2018 if (!assembly->save)
2021 sigbuffer_init (&buf, 32);
2023 sigbuffer_add_value (&buf, 0x06);
2024 /* encode custom attributes before the type */
2025 if (type->num_mods) {
2026 for (i = 0; i < type->num_mods; ++i) {
2029 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2030 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2032 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2034 token = type->modifiers [i].token;
2037 if (type->modifiers [i].required)
2038 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2040 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2042 sigbuffer_add_value (&buf, token);
2045 encode_type (assembly, type, &buf);
2046 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2047 sigbuffer_free (&buf);
2053 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2055 MONO_REQ_GC_UNSAFE_MODE;
2057 mono_error_init (error);
2061 guint32 typespec = 0;
2065 init_type_builder_generics (fb->type);
2067 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2068 return_val_if_nok (error, 0);
2069 klass = mono_class_from_mono_type (type);
2071 sigbuffer_init (&buf, 32);
2073 sigbuffer_add_value (&buf, 0x06);
2074 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2077 /* encode custom attributes before the type */
2079 if (klass->generic_container)
2080 typespec = create_typespec (assembly, type);
2083 MonoGenericClass *gclass;
2084 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2085 encode_generic_class (assembly, gclass, &buf);
2087 encode_type (assembly, type, &buf);
2089 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2090 sigbuffer_free (&buf);
2093 sigbuffer_free (&buf);
2098 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2100 MONO_REQ_GC_UNSAFE_MODE;
2102 char blob_size [64];
2103 char *b = blob_size;
2106 guint32 idx = 0, len = 0, dummy = 0;
2108 buf = (char *)g_malloc (64);
2110 *ret_type = MONO_TYPE_CLASS;
2112 box_val = (char*)&dummy;
2114 box_val = ((char*)val) + sizeof (MonoObject);
2115 *ret_type = val->vtable->klass->byval_arg.type;
2118 switch (*ret_type) {
2119 case MONO_TYPE_BOOLEAN:
2124 case MONO_TYPE_CHAR:
2141 case MONO_TYPE_VALUETYPE: {
2142 MonoClass *klass = val->vtable->klass;
2144 if (klass->enumtype) {
2145 *ret_type = mono_class_enum_basetype (klass)->type;
2147 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2150 g_error ("we can't encode valuetypes, we should have never reached this line");
2153 case MONO_TYPE_CLASS:
2155 case MONO_TYPE_STRING: {
2156 MonoString *str = (MonoString*)val;
2157 /* there is no signature */
2158 len = str->length * 2;
2159 mono_metadata_encode_value (len, b, &b);
2160 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2162 char *swapped = g_malloc (2 * mono_string_length (str));
2163 const char *p = (const char*)mono_string_chars (str);
2165 swap_with_size (swapped, p, 2, mono_string_length (str));
2166 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2170 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2176 case MONO_TYPE_GENERICINST:
2177 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2180 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2183 /* there is no signature */
2184 mono_metadata_encode_value (len, b, &b);
2185 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2186 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2187 swap_with_size (blob_size, box_val, len, 1);
2188 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2190 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2198 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2200 MONO_REQ_GC_UNSAFE_MODE;
2202 mono_error_init (error);
2208 sigbuffer_init (&buf, 32);
2210 sigbuffer_add_value (&buf, minfo->type);
2212 switch (minfo->type) {
2213 case MONO_NATIVE_BYVALTSTR:
2214 case MONO_NATIVE_BYVALARRAY:
2215 sigbuffer_add_value (&buf, minfo->count);
2217 case MONO_NATIVE_LPARRAY:
2218 if (minfo->eltype || minfo->has_size) {
2219 sigbuffer_add_value (&buf, minfo->eltype);
2220 if (minfo->has_size) {
2221 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2222 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2224 /* LAMESPEC: ElemMult is undocumented */
2225 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2229 case MONO_NATIVE_SAFEARRAY:
2231 sigbuffer_add_value (&buf, minfo->eltype);
2233 case MONO_NATIVE_CUSTOM:
2235 str = mono_string_to_utf8 (minfo->guid);
2237 sigbuffer_add_value (&buf, len);
2238 sigbuffer_add_mem (&buf, str, len);
2241 sigbuffer_add_value (&buf, 0);
2243 /* native type name */
2244 sigbuffer_add_value (&buf, 0);
2245 /* custom marshaler type name */
2246 if (minfo->marshaltype || minfo->marshaltyperef) {
2247 if (minfo->marshaltyperef) {
2248 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2249 if (!is_ok (error)) {
2250 sigbuffer_free (&buf);
2253 str = type_get_fully_qualified_name (marshaltype);
2255 str = mono_string_to_utf8 (minfo->marshaltype);
2257 sigbuffer_add_value (&buf, len);
2258 sigbuffer_add_mem (&buf, str, len);
2261 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2262 sigbuffer_add_value (&buf, 0);
2264 if (minfo->mcookie) {
2265 str = mono_string_to_utf8 (minfo->mcookie);
2267 sigbuffer_add_value (&buf, len);
2268 sigbuffer_add_mem (&buf, str, len);
2271 sigbuffer_add_value (&buf, 0);
2277 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2278 sigbuffer_free (&buf);
2283 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2285 MONO_REQ_GC_UNSAFE_MODE;
2287 mono_error_init (error);
2289 MonoDynamicTable *table;
2292 /* maybe this fixup should be done in the C# code */
2293 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2294 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2295 table = &assembly->tables [MONO_TABLE_FIELD];
2296 fb->table_idx = table->next_idx ++;
2297 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2298 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2299 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2300 values [MONO_FIELD_FLAGS] = fb->attrs;
2301 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2302 return_if_nok (error);
2305 if (fb->offset != -1) {
2306 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2308 alloc_table (table, table->rows);
2309 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2310 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2311 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2313 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2314 MonoTypeEnum field_type = (MonoTypeEnum)0;
2315 table = &assembly->tables [MONO_TABLE_CONSTANT];
2317 alloc_table (table, table->rows);
2318 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2319 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2320 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2321 values [MONO_CONSTANT_TYPE] = field_type;
2322 values [MONO_CONSTANT_PADDING] = 0;
2324 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2326 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2328 alloc_table (table, table->rows);
2329 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2330 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2332 * We store it in the code section because it's simpler for now.
2335 if (mono_array_length (fb->rva_data) >= 10)
2336 stream_data_align (&assembly->code);
2337 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2339 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2340 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2342 if (fb->marshal_info) {
2343 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2345 alloc_table (table, table->rows);
2346 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2347 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2348 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2349 return_if_nok (error);
2354 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2356 MONO_REQ_GC_UNSAFE_MODE;
2358 mono_error_init (error);
2361 guint32 nparams = 0;
2362 MonoReflectionMethodBuilder *mb = fb->get_method;
2363 MonoReflectionMethodBuilder *smb = fb->set_method;
2366 if (mb && mb->parameters)
2367 nparams = mono_array_length (mb->parameters);
2368 if (!mb && smb && smb->parameters)
2369 nparams = mono_array_length (smb->parameters) - 1;
2370 sigbuffer_init (&buf, 32);
2371 if (fb->call_conv & 0x20)
2372 sigbuffer_add_byte (&buf, 0x28);
2374 sigbuffer_add_byte (&buf, 0x08);
2375 sigbuffer_add_value (&buf, nparams);
2377 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2380 for (i = 0; i < nparams; ++i) {
2381 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2382 encode_reflection_type (assembly, pt, &buf, error);
2386 } else if (smb && smb->parameters) {
2387 /* the property type is the last param */
2388 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2392 for (i = 0; i < nparams; ++i) {
2393 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2394 encode_reflection_type (assembly, pt, &buf, error);
2399 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2404 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2405 sigbuffer_free (&buf);
2408 sigbuffer_free (&buf);
2413 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2415 MONO_REQ_GC_UNSAFE_MODE;
2417 mono_error_init (error);
2419 MonoDynamicTable *table;
2421 guint num_methods = 0;
2425 * we need to set things in the following tables:
2426 * PROPERTYMAP (info already filled in _get_type_info ())
2427 * PROPERTY (rows already preallocated in _get_type_info ())
2428 * METHOD (method info already done with the generic method code)
2432 table = &assembly->tables [MONO_TABLE_PROPERTY];
2433 pb->table_idx = table->next_idx ++;
2434 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2435 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2436 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2437 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2438 return_if_nok (error);
2441 /* FIXME: we still don't handle 'other' methods */
2442 if (pb->get_method) num_methods ++;
2443 if (pb->set_method) num_methods ++;
2445 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2446 table->rows += num_methods;
2447 alloc_table (table, table->rows);
2449 if (pb->get_method) {
2450 semaidx = table->next_idx ++;
2451 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2452 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2453 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2454 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2456 if (pb->set_method) {
2457 semaidx = table->next_idx ++;
2458 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2459 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2460 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2461 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2463 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2464 MonoTypeEnum field_type = (MonoTypeEnum)0;
2465 table = &assembly->tables [MONO_TABLE_CONSTANT];
2467 alloc_table (table, table->rows);
2468 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2469 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2470 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2471 values [MONO_CONSTANT_TYPE] = field_type;
2472 values [MONO_CONSTANT_PADDING] = 0;
2477 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2479 MONO_REQ_GC_UNSAFE_MODE;
2481 MonoDynamicTable *table;
2483 guint num_methods = 0;
2487 * we need to set things in the following tables:
2488 * EVENTMAP (info already filled in _get_type_info ())
2489 * EVENT (rows already preallocated in _get_type_info ())
2490 * METHOD (method info already done with the generic method code)
2493 table = &assembly->tables [MONO_TABLE_EVENT];
2494 eb->table_idx = table->next_idx ++;
2495 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2496 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2497 values [MONO_EVENT_FLAGS] = eb->attrs;
2498 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2499 return_if_nok (error);
2500 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2503 * FIXME: we still don't handle 'other' methods
2505 if (eb->add_method) num_methods ++;
2506 if (eb->remove_method) num_methods ++;
2507 if (eb->raise_method) num_methods ++;
2509 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2510 table->rows += num_methods;
2511 alloc_table (table, table->rows);
2513 if (eb->add_method) {
2514 semaidx = table->next_idx ++;
2515 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2516 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2517 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2518 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2520 if (eb->remove_method) {
2521 semaidx = table->next_idx ++;
2522 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2523 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2524 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2525 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2527 if (eb->raise_method) {
2528 semaidx = table->next_idx ++;
2529 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2530 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2531 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2532 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2537 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2539 MONO_REQ_GC_UNSAFE_MODE;
2541 mono_error_init (error);
2543 MonoDynamicTable *table;
2544 guint32 num_constraints, i;
2548 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2549 num_constraints = gparam->iface_constraints ?
2550 mono_array_length (gparam->iface_constraints) : 0;
2551 table->rows += num_constraints;
2552 if (gparam->base_type)
2554 alloc_table (table, table->rows);
2556 if (gparam->base_type) {
2557 table_idx = table->next_idx ++;
2558 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2560 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2561 return_if_nok (error);
2562 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2563 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2566 for (i = 0; i < num_constraints; i++) {
2567 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2568 gparam->iface_constraints, gpointer, i);
2570 table_idx = table->next_idx ++;
2571 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2573 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2574 return_if_nok (error);
2576 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2577 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2582 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2584 MONO_REQ_GC_UNSAFE_MODE;
2586 GenericParamTableEntry *entry;
2589 * The GenericParam table must be sorted according to the `owner' field.
2590 * We need to do this sorting prior to writing the GenericParamConstraint
2591 * table, since we have to use the final GenericParam table indices there
2592 * and they must also be sorted.
2595 entry = g_new0 (GenericParamTableEntry, 1);
2596 entry->owner = owner;
2597 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2598 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2599 entry->gparam = gparam;
2601 g_ptr_array_add (assembly->gen_params, entry);
2605 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2607 MONO_REQ_GC_UNSAFE_MODE;
2609 MonoDynamicTable *table;
2610 MonoGenericParam *param;
2614 mono_error_init (error);
2616 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2617 table_idx = table->next_idx ++;
2618 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2620 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2621 return_val_if_nok (error, FALSE);
2623 param = gparam_type->data.generic_param;
2625 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2626 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2627 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2628 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2630 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2633 encode_constraints (entry->gparam, table_idx, assembly, error);
2634 return_val_if_nok (error, FALSE);
2640 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2642 MONO_REQ_GC_UNSAFE_MODE;
2644 MonoDynamicTable *table;
2647 guint32 cols [MONO_ASSEMBLY_SIZE];
2651 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2654 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2655 table = &assembly->tables [MONO_TABLE_MODULEREF];
2656 token = table->next_idx ++;
2658 alloc_table (table, table->rows);
2659 values = table->values + token * MONO_MODULEREF_SIZE;
2660 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2662 token <<= MONO_RESOLUTION_SCOPE_BITS;
2663 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2664 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2669 if (assembly_is_dynamic (image->assembly))
2671 memset (cols, 0, sizeof (cols));
2673 /* image->assembly->image is the manifest module */
2674 image = image->assembly->image;
2675 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2678 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2679 token = table->next_idx ++;
2681 alloc_table (table, table->rows);
2682 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2683 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2684 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2685 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2686 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2687 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2688 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2689 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2690 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2692 if (strcmp ("", image->assembly->aname.culture)) {
2693 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2694 image->assembly->aname.culture);
2697 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2698 guchar pubtoken [9];
2700 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2701 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2703 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2705 token <<= MONO_RESOLUTION_SCOPE_BITS;
2706 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2707 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2712 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2714 MONO_REQ_GC_NEUTRAL_MODE;
2716 MonoDynamicTable *table;
2721 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2724 sigbuffer_init (&buf, 32);
2725 switch (type->type) {
2726 case MONO_TYPE_FNPTR:
2728 case MONO_TYPE_SZARRAY:
2729 case MONO_TYPE_ARRAY:
2731 case MONO_TYPE_MVAR:
2732 case MONO_TYPE_GENERICINST:
2733 encode_type (assembly, type, &buf);
2735 case MONO_TYPE_CLASS:
2736 case MONO_TYPE_VALUETYPE: {
2737 MonoClass *k = mono_class_from_mono_type (type);
2738 if (!k || !k->generic_container) {
2739 sigbuffer_free (&buf);
2742 encode_type (assembly, type, &buf);
2746 sigbuffer_free (&buf);
2750 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2751 if (assembly->save) {
2752 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2753 alloc_table (table, table->rows + 1);
2754 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2755 values [MONO_TYPESPEC_SIGNATURE] = token;
2757 sigbuffer_free (&buf);
2759 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2760 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2766 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2768 MONO_REQ_GC_UNSAFE_MODE;
2770 MonoDynamicTable *table;
2772 guint32 token, scope, enclosing;
2775 /* if the type requires a typespec, we must try that first*/
2776 if (try_typespec && (token = create_typespec (assembly, type)))
2778 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2781 klass = mono_class_from_mono_type (type);
2783 klass = mono_class_from_mono_type (type);
2786 * If it's in the same module and not a generic type parameter:
2788 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2789 (type->type != MONO_TYPE_MVAR)) {
2790 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2791 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2792 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2796 if (klass->nested_in) {
2797 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2798 /* get the typeref idx of the enclosing type */
2799 enclosing >>= MONO_TYPEDEFORREF_BITS;
2800 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2802 scope = resolution_scope_from_image (assembly, klass->image);
2804 table = &assembly->tables [MONO_TABLE_TYPEREF];
2805 if (assembly->save) {
2806 alloc_table (table, table->rows + 1);
2807 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2808 values [MONO_TYPEREF_SCOPE] = scope;
2809 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2810 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2812 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2813 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2815 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2820 * Despite the name, we handle also TypeSpec (with the above helper).
2823 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2825 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2828 #ifndef DISABLE_REFLECTION_EMIT
2830 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2832 MONO_REQ_GC_NEUTRAL_MODE;
2834 MonoDynamicTable *table;
2836 guint32 token, pclass;
2838 switch (parent & MONO_TYPEDEFORREF_MASK) {
2839 case MONO_TYPEDEFORREF_TYPEREF:
2840 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2842 case MONO_TYPEDEFORREF_TYPESPEC:
2843 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2845 case MONO_TYPEDEFORREF_TYPEDEF:
2846 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2849 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2852 /* extract the index */
2853 parent >>= MONO_TYPEDEFORREF_BITS;
2855 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2857 if (assembly->save) {
2858 alloc_table (table, table->rows + 1);
2859 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2860 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2861 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2862 values [MONO_MEMBERREF_SIGNATURE] = sig;
2865 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2872 * Insert a memberef row into the metadata: the token that point to the memberref
2873 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2874 * mono_image_get_fieldref_token()).
2875 * The sig param is an index to an already built signature.
2878 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2880 MONO_REQ_GC_NEUTRAL_MODE;
2882 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2883 return mono_image_add_memberef_row (assembly, parent, name, sig);
2888 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2890 MONO_REQ_GC_NEUTRAL_MODE;
2893 MonoMethodSignature *sig;
2895 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2897 if (create_typespec) {
2898 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2903 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2904 if (token && !create_typespec)
2907 g_assert (!method->is_inflated);
2910 * A methodref signature can't contain an unmanaged calling convention.
2912 sig = mono_metadata_signature_dup (mono_method_signature (method));
2913 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2914 sig->call_convention = MONO_CALL_DEFAULT;
2915 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2916 method->name, method_encode_signature (assembly, sig));
2918 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2921 if (create_typespec) {
2922 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2923 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2924 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2926 if (assembly->save) {
2929 alloc_table (table, table->rows + 1);
2930 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2931 values [MONO_METHODSPEC_METHOD] = token;
2932 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2935 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2937 /*methodspec and memberef tokens are diferent, */
2938 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2945 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2947 guint32 token, parent, sig;
2948 ReflectionMethodBuilder rmb;
2949 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2951 mono_error_init (error);
2952 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2956 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2960 * A methodref signature can't contain an unmanaged calling convention.
2961 * Since some flags are encoded as part of call_conv, we need to check against it.
2963 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2964 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2966 sig = method_builder_encode_signature (assembly, &rmb, error);
2967 return_val_if_nok (error, 0);
2969 if (tb->generic_params) {
2970 parent = create_generic_typespec (assembly, tb, error);
2971 return_val_if_nok (error, 0);
2973 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2974 return_val_if_nok (error, 0);
2976 parent = mono_image_typedef_or_ref (assembly, t);
2979 char *name = mono_string_to_utf8 (method->name);
2981 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2984 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2990 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2991 const gchar *name, guint32 sig)
2993 MonoDynamicTable *table;
2997 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2999 if (assembly->save) {
3000 alloc_table (table, table->rows + 1);
3001 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3002 values [MONO_MEMBERREF_CLASS] = original;
3003 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3004 values [MONO_MEMBERREF_SIGNATURE] = sig;
3007 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3014 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3018 guint32 nparams = mono_array_length (mb->generic_params);
3021 if (!assembly->save)
3024 sigbuffer_init (&buf, 32);
3026 sigbuffer_add_value (&buf, 0xa);
3027 sigbuffer_add_value (&buf, nparams);
3029 for (i = 0; i < nparams; i++) {
3030 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3031 sigbuffer_add_value (&buf, i);
3034 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3035 sigbuffer_free (&buf);
3040 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3042 MonoDynamicTable *table;
3044 guint32 token, mtoken = 0;
3046 mono_error_init (error);
3047 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3051 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3053 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3054 if (!mono_error_ok (error))
3057 switch (mono_metadata_token_table (mtoken)) {
3058 case MONO_TABLE_MEMBERREF:
3059 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3061 case MONO_TABLE_METHOD:
3062 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3065 g_assert_not_reached ();
3068 if (assembly->save) {
3069 alloc_table (table, table->rows + 1);
3070 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3071 values [MONO_METHODSPEC_METHOD] = mtoken;
3072 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3075 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3078 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3083 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3087 mono_error_init (error);
3089 if (mb->generic_params && create_methodspec)
3090 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3092 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3096 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3097 if (!mono_error_ok (error))
3099 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3104 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3106 guint32 token, parent, sig;
3107 ReflectionMethodBuilder rmb;
3109 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3111 mono_error_init (error);
3113 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3117 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3120 if (tb->generic_params) {
3121 parent = create_generic_typespec (assembly, tb, error);
3122 return_val_if_nok (error, 0);
3124 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3125 return_val_if_nok (error, 0);
3126 parent = mono_image_typedef_or_ref (assembly, type);
3129 name = mono_string_to_utf8 (rmb.name);
3130 sig = method_builder_encode_signature (assembly, &rmb, error);
3131 return_val_if_nok (error, 0);
3133 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3136 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3142 is_field_on_inst (MonoClassField *field)
3144 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3148 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3151 get_field_on_inst_generic_type (MonoClassField *field)
3153 MonoClass *klass, *gtd;
3154 MonoDynamicGenericClass *dgclass;
3157 g_assert (is_field_on_inst (field));
3159 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3161 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3162 field_index = field - dgclass->fields;
3163 return dgclass->field_generic_types [field_index];
3166 klass = field->parent;
3167 gtd = klass->generic_class->container_class;
3169 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3170 field_index = field - klass->fields;
3171 return gtd->fields [field_index].type;
3174 g_assert_not_reached ();
3178 #ifndef DISABLE_REFLECTION_EMIT
3180 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3186 g_assert (field->parent);
3188 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3192 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3193 int index = field - field->parent->fields;
3194 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3196 if (is_field_on_inst (field))
3197 type = get_field_on_inst_generic_type (field);
3199 type = mono_field_get_type (field);
3201 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3202 mono_field_get_name (field),
3203 fieldref_encode_signature (assembly, field->parent->image, type));
3204 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3209 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3213 MonoGenericClass *gclass;
3217 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3220 if (is_sre_field_builder (mono_object_class (f->fb))) {
3221 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3222 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3223 return_val_if_nok (error, 0);
3224 klass = mono_class_from_mono_type (type);
3225 gclass = type->data.generic_class;
3226 g_assert (gclass->is_dynamic);
3228 guint32 sig_token = field_encode_signature (assembly, fb, error);
3229 return_val_if_nok (error, 0);
3230 name = mono_string_to_utf8 (fb->name);
3231 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3233 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3235 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3237 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3238 return_val_if_nok (error, 0);
3239 klass = mono_class_from_mono_type (type);
3241 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3242 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3244 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3245 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3248 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3253 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3257 MonoGenericClass *gclass;
3260 mono_error_init (error);
3262 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3264 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3268 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3269 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3270 ReflectionMethodBuilder rmb;
3273 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3274 return_val_if_nok (error, 0);
3275 klass = mono_class_from_mono_type (type);
3277 gclass = type->data.generic_class;
3278 g_assert (gclass->is_dynamic);
3280 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3283 sig = method_builder_encode_signature (assembly, &rmb, error);
3284 return_val_if_nok (error, 0);
3286 name = mono_string_to_utf8 (rmb.name);
3288 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3290 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3291 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3293 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3294 return_val_if_nok (error, 0);
3295 klass = mono_class_from_mono_type (type);
3297 sig = method_encode_signature (assembly, mono_method_signature (mm));
3298 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3300 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3301 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3305 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3310 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3313 MonoGenericContext tmp_context;
3314 MonoType **type_argv;
3315 MonoGenericInst *ginst;
3316 MonoMethod *method, *inflated;
3319 mono_error_init (error);
3321 init_type_builder_generics ((MonoObject*)m->inst);
3323 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3324 return_val_if_nok (error, NULL);
3326 klass = method->klass;
3328 if (m->method_args == NULL)
3331 if (method->is_inflated)
3332 method = ((MonoMethodInflated *) method)->declaring;
3334 count = mono_array_length (m->method_args);
3336 type_argv = g_new0 (MonoType *, count);
3337 for (i = 0; i < count; i++) {
3338 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3339 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3340 return_val_if_nok (error, NULL);
3342 ginst = mono_metadata_get_generic_inst (count, type_argv);
3345 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3346 tmp_context.method_inst = ginst;
3348 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3349 mono_error_assert_ok (error);
3354 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3356 guint32 sig, token = 0;
3360 mono_error_init (error);
3362 if (m->method_args) {
3363 MonoMethod *inflated;
3365 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3366 return_val_if_nok (error, 0);
3368 if (create_methodspec)
3369 token = mono_image_get_methodspec_token (assembly, inflated);
3371 token = mono_image_get_inflated_method_token (assembly, inflated);
3375 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3379 if (is_sre_method_builder (mono_object_class (m->mb))) {
3380 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3381 MonoGenericClass *gclass;
3382 ReflectionMethodBuilder rmb;
3385 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3386 return_val_if_nok (error, 0);
3387 klass = mono_class_from_mono_type (type);
3388 gclass = type->data.generic_class;
3389 g_assert (gclass->is_dynamic);
3391 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3394 sig = method_builder_encode_signature (assembly, &rmb, error);
3395 return_val_if_nok (error, 0);
3397 name = mono_string_to_utf8 (rmb.name);
3399 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3401 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3402 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3404 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3405 return_val_if_nok (error, 0);
3406 klass = mono_class_from_mono_type (type);
3408 sig = method_encode_signature (assembly, mono_method_signature (mm));
3409 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3411 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3412 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3415 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3420 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3424 guint32 nparams = context->method_inst->type_argc;
3427 if (!assembly->save)
3430 sigbuffer_init (&buf, 32);
3432 * FIXME: vararg, explicit_this, differenc call_conv values...
3434 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3435 sigbuffer_add_value (&buf, nparams);
3437 for (i = 0; i < nparams; i++)
3438 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3440 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3441 sigbuffer_free (&buf);
3446 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3448 MonoDynamicTable *table;
3450 guint32 token, mtoken = 0, sig;
3451 MonoMethodInflated *imethod;
3452 MonoMethod *declaring;
3454 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3456 g_assert (method->is_inflated);
3457 imethod = (MonoMethodInflated *) method;
3458 declaring = imethod->declaring;
3460 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3461 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3463 if (!mono_method_signature (declaring)->generic_param_count)
3466 switch (mono_metadata_token_table (mtoken)) {
3467 case MONO_TABLE_MEMBERREF:
3468 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3470 case MONO_TABLE_METHOD:
3471 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3474 g_assert_not_reached ();
3477 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3479 if (assembly->save) {
3480 alloc_table (table, table->rows + 1);
3481 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3482 values [MONO_METHODSPEC_METHOD] = mtoken;
3483 values [MONO_METHODSPEC_SIGNATURE] = sig;
3486 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3493 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3495 MonoMethodInflated *imethod;
3498 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3502 g_assert (method->is_inflated);
3503 imethod = (MonoMethodInflated *) method;
3505 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3506 token = method_encode_methodspec (assembly, method);
3508 guint32 sig = method_encode_signature (
3509 assembly, mono_method_signature (imethod->declaring));
3510 token = mono_image_get_memberref_token (
3511 assembly, &method->klass->byval_arg, method->name, sig);
3514 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3519 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3521 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3524 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3525 token = mono_image_get_memberref_token (
3526 assembly, &m->klass->byval_arg, m->name, sig);
3532 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3534 MonoDynamicTable *table;
3543 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3544 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3545 * Because of this, we must not insert it into the `typeref' hash table.
3547 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3548 return_val_if_nok (error, 0);
3549 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3553 sigbuffer_init (&buf, 32);
3555 g_assert (tb->generic_params);
3556 klass = mono_class_from_mono_type (type);
3558 if (tb->generic_container)
3559 mono_reflection_create_generic_class (tb);
3561 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3562 g_assert (klass->generic_container);
3563 sigbuffer_add_value (&buf, klass->byval_arg.type);
3564 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3566 count = mono_array_length (tb->generic_params);
3567 sigbuffer_add_value (&buf, count);
3568 for (i = 0; i < count; i++) {
3569 MonoReflectionGenericParam *gparam;
3571 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3572 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3576 encode_type (assembly, gparam_type, &buf);
3579 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3581 if (assembly->save) {
3582 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3583 alloc_table (table, table->rows + 1);
3584 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3585 values [MONO_TYPESPEC_SIGNATURE] = token;
3587 sigbuffer_free (&buf);
3589 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3590 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3594 sigbuffer_free (&buf);
3599 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3602 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3604 int i, count, len, pos;
3607 mono_error_init (error);
3611 count += mono_array_length (modreq);
3613 count += mono_array_length (modopt);
3616 return mono_metadata_type_dup (NULL, type);
3618 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3619 t = (MonoType *)g_malloc (len);
3620 memcpy (t, type, MONO_SIZEOF_TYPE);
3622 t->num_mods = count;
3625 for (i = 0; i < mono_array_length (modreq); ++i) {
3626 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3629 t->modifiers [pos].required = 1;
3630 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3635 for (i = 0; i < mono_array_length (modopt); ++i) {
3636 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3639 t->modifiers [pos].required = 0;
3640 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3652 init_type_builder_generics (MonoObject *type)
3654 MonoReflectionTypeBuilder *tb;
3656 if (!is_sre_type_builder(mono_object_class (type)))
3658 tb = (MonoReflectionTypeBuilder *)type;
3660 if (tb && tb->generic_container)
3661 mono_reflection_create_generic_class (tb);
3665 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3667 MonoDynamicTable *table;
3668 MonoType *custom = NULL, *type;
3670 guint32 token, pclass, parent, sig;
3673 mono_error_init (error);
3675 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3679 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3680 return_val_if_nok (error, 0);
3681 /* FIXME: is this call necessary? */
3682 mono_class_from_mono_type (typeb);
3684 /*FIXME this is one more layer of ugliness due how types are created.*/
3685 init_type_builder_generics (fb->type);
3687 /* fb->type does not include the custom modifiers */
3688 /* FIXME: We should do this in one place when a fieldbuilder is created */
3689 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3690 return_val_if_nok (error, 0);
3692 if (fb->modreq || fb->modopt) {
3693 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3694 return_val_if_nok (error, 0);
3697 sig = fieldref_encode_signature (assembly, NULL, type);
3700 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3701 return_val_if_nok (error, 0);
3702 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3704 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3705 parent >>= MONO_TYPEDEFORREF_BITS;
3707 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3709 name = mono_string_to_utf8 (fb->name);
3711 if (assembly->save) {
3712 alloc_table (table, table->rows + 1);
3713 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3714 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3715 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3716 values [MONO_MEMBERREF_SIGNATURE] = sig;
3719 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3721 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3727 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3733 mono_error_init (error);
3735 if (!assembly->save)
3738 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3739 g_assert (helper->type == 2);
3741 if (helper->arguments)
3742 nargs = mono_array_length (helper->arguments);
3746 sigbuffer_init (&buf, 32);
3748 /* Encode calling convention */
3749 /* Change Any to Standard */
3750 if ((helper->call_conv & 0x03) == 0x03)
3751 helper->call_conv = 0x01;
3752 /* explicit_this implies has_this */
3753 if (helper->call_conv & 0x40)
3754 helper->call_conv &= 0x20;
3756 if (helper->call_conv == 0) { /* Unmanaged */
3757 idx = helper->unmanaged_call_conv - 1;
3760 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3761 if (helper->call_conv & 0x02) /* varargs */
3765 sigbuffer_add_byte (&buf, idx);
3766 sigbuffer_add_value (&buf, nargs);
3767 encode_reflection_type (assembly, helper->return_type, &buf, error);
3770 for (i = 0; i < nargs; ++i) {
3771 MonoArray *modreqs = NULL;
3772 MonoArray *modopts = NULL;
3773 MonoReflectionType *pt;
3775 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3776 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3777 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3778 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3780 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3783 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3784 encode_reflection_type (assembly, pt, &buf, error);
3788 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3789 sigbuffer_free (&buf);
3793 sigbuffer_free (&buf);
3798 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3801 MonoDynamicTable *table;
3804 mono_error_init (error);
3806 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3807 idx = table->next_idx ++;
3809 alloc_table (table, table->rows);
3810 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3812 values [MONO_STAND_ALONE_SIGNATURE] =
3813 mono_reflection_encode_sighelper (assembly, helper, error);
3814 return_val_if_nok (error, 0);
3820 reflection_cc_to_file (int call_conv) {
3821 switch (call_conv & 0x3) {
3823 case 1: return MONO_CALL_DEFAULT;
3824 case 2: return MONO_CALL_VARARG;
3826 g_assert_not_reached ();
3830 #endif /* !DISABLE_REFLECTION_EMIT */
3834 MonoMethodSignature *sig;
3839 #ifndef DISABLE_REFLECTION_EMIT
3841 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3846 MonoMethodSignature *sig;
3847 ArrayMethod *am = NULL;
3850 mono_error_init (error);
3852 nparams = mono_array_length (m->parameters);
3853 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3855 sig->sentinelpos = -1;
3856 sig->call_convention = reflection_cc_to_file (m->call_conv);
3857 sig->param_count = nparams;
3859 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3863 sig->ret = &mono_defaults.void_class->byval_arg;
3865 mtype = mono_reflection_type_get_handle (m->parent, error);
3869 for (i = 0; i < nparams; ++i) {
3870 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3875 name = mono_string_to_utf8 (m->name);
3876 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3877 am = (ArrayMethod *)tmp->data;
3878 if (strcmp (name, am->name) == 0 &&
3879 mono_metadata_type_equal (am->parent, mtype) &&
3880 mono_metadata_signature_equal (am->sig, sig)) {
3883 m->table_idx = am->token & 0xffffff;
3887 am = g_new0 (ArrayMethod, 1);
3891 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3892 method_encode_signature (assembly, sig));
3893 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3894 m->table_idx = am->token & 0xffffff;
3905 * Insert into the metadata tables all the info about the TypeBuilder tb.
3906 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3909 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3911 MonoDynamicTable *table;
3913 int i, is_object = 0, is_system = 0;
3916 mono_error_init (error);
3918 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3919 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3920 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3921 n = mono_string_to_utf8 (tb->name);
3922 if (strcmp (n, "Object") == 0)
3924 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3926 n = mono_string_to_utf8 (tb->nspace);
3927 if (strcmp (n, "System") == 0)
3929 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3931 if (tb->parent && !(is_system && is_object) &&
3932 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3933 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3934 return_val_if_nok (error, FALSE);
3935 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3937 values [MONO_TYPEDEF_EXTENDS] = 0;
3939 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3940 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3943 * if we have explicitlayout or sequentiallayouts, output data in the
3944 * ClassLayout table.
3946 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3947 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3948 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3950 alloc_table (table, table->rows);
3951 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3952 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3953 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3954 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3957 /* handle interfaces */
3958 if (tb->interfaces) {
3959 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3961 table->rows += mono_array_length (tb->interfaces);
3962 alloc_table (table, table->rows);
3963 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3964 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3965 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3966 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3967 return_val_if_nok (error, FALSE);
3968 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3969 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3970 values += MONO_INTERFACEIMPL_SIZE;
3976 table = &assembly->tables [MONO_TABLE_FIELD];
3977 table->rows += tb->num_fields;
3978 alloc_table (table, table->rows);
3979 for (i = 0; i < tb->num_fields; ++i) {
3980 mono_image_get_field_info (
3981 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3982 return_val_if_nok (error, FALSE);
3986 /* handle constructors */
3988 table = &assembly->tables [MONO_TABLE_METHOD];
3989 table->rows += mono_array_length (tb->ctors);
3990 alloc_table (table, table->rows);
3991 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3992 if (!mono_image_get_ctor_info (domain,
3993 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3999 /* handle methods */
4001 table = &assembly->tables [MONO_TABLE_METHOD];
4002 table->rows += tb->num_methods;
4003 alloc_table (table, table->rows);
4004 for (i = 0; i < tb->num_methods; ++i) {
4005 if (!mono_image_get_method_info (
4006 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4011 /* Do the same with properties etc.. */
4012 if (tb->events && mono_array_length (tb->events)) {
4013 table = &assembly->tables [MONO_TABLE_EVENT];
4014 table->rows += mono_array_length (tb->events);
4015 alloc_table (table, table->rows);
4016 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4018 alloc_table (table, table->rows);
4019 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4020 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4021 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4022 for (i = 0; i < mono_array_length (tb->events); ++i) {
4023 mono_image_get_event_info (
4024 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4025 return_val_if_nok (error, FALSE);
4028 if (tb->properties && mono_array_length (tb->properties)) {
4029 table = &assembly->tables [MONO_TABLE_PROPERTY];
4030 table->rows += mono_array_length (tb->properties);
4031 alloc_table (table, table->rows);
4032 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4034 alloc_table (table, table->rows);
4035 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4036 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4037 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4038 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4039 mono_image_get_property_info (
4040 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4041 return_val_if_nok (error, FALSE);
4045 /* handle generic parameters */
4046 if (tb->generic_params) {
4047 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4048 table->rows += mono_array_length (tb->generic_params);
4049 alloc_table (table, table->rows);
4050 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4051 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4053 mono_image_get_generic_param_info (
4054 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4058 mono_image_add_decl_security (assembly,
4059 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4062 MonoDynamicTable *ntable;
4064 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4065 ntable->rows += mono_array_length (tb->subtypes);
4066 alloc_table (ntable, ntable->rows);
4067 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4069 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4070 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4072 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4073 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4074 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4075 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4076 mono_string_to_utf8 (tb->name), tb->table_idx,
4077 ntable->next_idx, ntable->rows);*/
4078 values += MONO_NESTED_CLASS_SIZE;
4088 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4092 mono_ptr_array_append (*types, type);
4094 if (!type->subtypes)
4097 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4098 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4099 collect_types (types, subtype);
4104 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4106 if ((*type1)->table_idx < (*type2)->table_idx)
4109 if ((*type1)->table_idx > (*type2)->table_idx)
4116 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4119 mono_error_init (error);
4122 for (i = 0; i < mono_array_length (pinfo); ++i) {
4123 MonoReflectionParamBuilder *pb;
4124 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4127 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4135 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4138 mono_error_init (error);
4140 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4143 for (i = 0; i < tb->num_fields; ++i) {
4144 MonoReflectionFieldBuilder* fb;
4145 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4146 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4151 for (i = 0; i < mono_array_length (tb->events); ++i) {
4152 MonoReflectionEventBuilder* eb;
4153 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4154 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4158 if (tb->properties) {
4159 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4160 MonoReflectionPropertyBuilder* pb;
4161 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4162 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4167 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4168 MonoReflectionCtorBuilder* cb;
4169 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4170 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4171 !params_add_cattrs (assembly, cb->pinfo, error))
4177 for (i = 0; i < tb->num_methods; ++i) {
4178 MonoReflectionMethodBuilder* mb;
4179 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4180 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4181 !params_add_cattrs (assembly, mb->pinfo, error))
4187 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4188 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4197 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4201 mono_error_init (error);
4203 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4206 if (moduleb->global_methods) {
4207 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4208 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4209 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4210 !params_add_cattrs (assembly, mb->pinfo, error))
4215 if (moduleb->global_fields) {
4216 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4217 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4218 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4223 if (moduleb->types) {
4224 for (i = 0; i < moduleb->num_types; ++i) {
4225 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4234 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4236 MonoDynamicTable *table;
4240 char *b = blob_size;
4243 table = &assembly->tables [MONO_TABLE_FILE];
4245 alloc_table (table, table->rows);
4246 values = table->values + table->next_idx * MONO_FILE_SIZE;
4247 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4248 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4249 if (image_is_dynamic (module->image)) {
4250 /* This depends on the fact that the main module is emitted last */
4251 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4252 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4255 path = g_strdup (module->image->name);
4257 mono_sha1_get_digest_from_file (path, hash);
4260 mono_metadata_encode_value (20, b, &b);
4261 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4262 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4267 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4269 MonoDynamicTable *table;
4272 table = &assembly->tables [MONO_TABLE_MODULE];
4273 mb->table_idx = table->next_idx ++;
4274 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4275 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4278 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4279 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4280 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4281 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4285 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4286 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4288 MonoDynamicTable *table;
4292 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4293 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4296 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4298 alloc_table (table, table->rows);
4299 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4301 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4302 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4303 if (klass->nested_in)
4304 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4306 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4307 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4308 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4310 res = table->next_idx;
4314 /* Emit nested types */
4315 if (klass->ext && klass->ext->nested_classes) {
4318 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4319 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4326 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4327 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4333 mono_error_init (error);
4335 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4336 return_if_nok (error);
4338 klass = mono_class_from_mono_type (t);
4340 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4342 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4343 parent_index, assembly);
4347 * We need to do this ourselves since klass->nested_classes is not set up.
4350 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4351 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4352 return_if_nok (error);
4358 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4359 guint32 module_index, MonoDynamicImage *assembly)
4361 MonoImage *image = module->image;
4365 t = &image->tables [MONO_TABLE_TYPEDEF];
4367 for (i = 0; i < t->rows; ++i) {
4369 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4370 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4372 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4373 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4378 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4380 MonoDynamicTable *table;
4382 guint32 scope, scope_idx, impl, current_idx;
4383 gboolean forwarder = TRUE;
4384 gpointer iter = NULL;
4387 if (klass->nested_in) {
4388 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4391 scope = resolution_scope_from_image (assembly, klass->image);
4392 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4393 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4394 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4397 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4400 alloc_table (table, table->rows);
4401 current_idx = table->next_idx;
4402 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4404 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4405 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4406 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4407 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4408 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4412 while ((nested = mono_class_get_nested_types (klass, &iter)))
4413 add_exported_type (assemblyb, assembly, nested, current_idx);
4417 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4423 if (!assemblyb->type_forwarders)
4426 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4427 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4432 type = mono_reflection_type_get_handle (t, &error);
4433 mono_error_assert_ok (&error);
4436 klass = mono_class_from_mono_type (type);
4438 add_exported_type (assemblyb, assembly, klass, 0);
4442 #define align_pointer(base,p)\
4444 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4446 (p) += 4 - (__diff & 3);\
4450 compare_constants (const void *a, const void *b)
4452 const guint32 *a_values = (const guint32 *)a;
4453 const guint32 *b_values = (const guint32 *)b;
4454 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4458 compare_semantics (const void *a, const void *b)
4460 const guint32 *a_values = (const guint32 *)a;
4461 const guint32 *b_values = (const guint32 *)b;
4462 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4465 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4469 compare_custom_attrs (const void *a, const void *b)
4471 const guint32 *a_values = (const guint32 *)a;
4472 const guint32 *b_values = (const guint32 *)b;
4474 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4478 compare_field_marshal (const void *a, const void *b)
4480 const guint32 *a_values = (const guint32 *)a;
4481 const guint32 *b_values = (const guint32 *)b;
4483 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4487 compare_nested (const void *a, const void *b)
4489 const guint32 *a_values = (const guint32 *)a;
4490 const guint32 *b_values = (const guint32 *)b;
4492 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4496 compare_genericparam (const void *a, const void *b)
4499 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4500 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4502 if ((*b_entry)->owner == (*a_entry)->owner) {
4503 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4504 mono_error_assert_ok (&error);
4505 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4506 mono_error_assert_ok (&error);
4508 mono_type_get_generic_param_num (a_type) -
4509 mono_type_get_generic_param_num (b_type);
4511 return (*a_entry)->owner - (*b_entry)->owner;
4515 compare_declsecurity_attrs (const void *a, const void *b)
4517 const guint32 *a_values = (const guint32 *)a;
4518 const guint32 *b_values = (const guint32 *)b;
4520 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4524 compare_interface_impl (const void *a, const void *b)
4526 const guint32 *a_values = (const guint32 *)a;
4527 const guint32 *b_values = (const guint32 *)b;
4529 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4533 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4537 pad_heap (MonoDynamicStream *sh)
4539 if (sh->index & 3) {
4540 int sz = 4 - (sh->index & 3);
4541 memset (sh->data + sh->index, 0, sz);
4548 MonoDynamicStream *stream;
4552 * build_compressed_metadata() fills in the blob of data that represents the
4553 * raw metadata as it will be saved in the PE file. The five streams are output
4554 * and the metadata tables are comnpressed from the guint32 array representation,
4555 * to the compressed on-disk format.
4558 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4560 MonoDynamicTable *table;
4562 guint64 valid_mask = 0;
4563 guint64 sorted_mask;
4564 guint32 heapt_size = 0;
4565 guint32 meta_size = 256; /* allow for header and other stuff */
4566 guint32 table_offset;
4567 guint32 ntables = 0;
4573 struct StreamDesc stream_desc [5];
4575 mono_error_init (error);
4577 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4578 for (i = 0; i < assembly->gen_params->len; i++) {
4579 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4580 if (!write_generic_param_entry (assembly, entry, error))
4584 stream_desc [0].name = "#~";
4585 stream_desc [0].stream = &assembly->tstream;
4586 stream_desc [1].name = "#Strings";
4587 stream_desc [1].stream = &assembly->sheap;
4588 stream_desc [2].name = "#US";
4589 stream_desc [2].stream = &assembly->us;
4590 stream_desc [3].name = "#Blob";
4591 stream_desc [3].stream = &assembly->blob;
4592 stream_desc [4].name = "#GUID";
4593 stream_desc [4].stream = &assembly->guid;
4595 /* tables that are sorted */
4596 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4597 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4598 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4599 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4600 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4601 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4602 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4604 /* Compute table sizes */
4605 /* the MonoImage has already been created in mono_image_basic_init() */
4606 meta = &assembly->image;
4608 /* sizes should be multiple of 4 */
4609 pad_heap (&assembly->blob);
4610 pad_heap (&assembly->guid);
4611 pad_heap (&assembly->sheap);
4612 pad_heap (&assembly->us);
4614 /* Setup the info used by compute_sizes () */
4615 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4616 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4617 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4619 meta_size += assembly->blob.index;
4620 meta_size += assembly->guid.index;
4621 meta_size += assembly->sheap.index;
4622 meta_size += assembly->us.index;
4624 for (i=0; i < MONO_TABLE_NUM; ++i)
4625 meta->tables [i].rows = assembly->tables [i].rows;
4627 for (i = 0; i < MONO_TABLE_NUM; i++){
4628 if (meta->tables [i].rows == 0)
4630 valid_mask |= (guint64)1 << i;
4632 meta->tables [i].row_size = mono_metadata_compute_size (
4633 meta, i, &meta->tables [i].size_bitfield);
4634 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4636 heapt_size += 24; /* #~ header size */
4637 heapt_size += ntables * 4;
4638 /* make multiple of 4 */
4641 meta_size += heapt_size;
4642 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4643 p = (unsigned char*)meta->raw_metadata;
4644 /* the metadata signature */
4645 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4646 /* version numbers and 4 bytes reserved */
4647 int16val = (guint16*)p;
4648 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4649 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4651 /* version string */
4652 int32val = (guint32*)p;
4653 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4655 memcpy (p, meta->version, strlen (meta->version));
4656 p += GUINT32_FROM_LE (*int32val);
4657 align_pointer (meta->raw_metadata, p);
4658 int16val = (guint16*)p;
4659 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4660 *int16val = GUINT16_TO_LE (5); /* number of streams */
4664 * write the stream info.
4666 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4667 table_offset += 3; table_offset &= ~3;
4669 assembly->tstream.index = heapt_size;
4670 for (i = 0; i < 5; ++i) {
4671 int32val = (guint32*)p;
4672 stream_desc [i].stream->offset = table_offset;
4673 *int32val++ = GUINT32_TO_LE (table_offset);
4674 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4675 table_offset += GUINT32_FROM_LE (*int32val);
4676 table_offset += 3; table_offset &= ~3;
4678 strcpy ((char*)p, stream_desc [i].name);
4679 p += strlen (stream_desc [i].name) + 1;
4680 align_pointer (meta->raw_metadata, p);
4683 * now copy the data, the table stream header and contents goes first.
4685 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4686 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4687 int32val = (guint32*)p;
4688 *int32val = GUINT32_TO_LE (0); /* reserved */
4691 *p++ = 2; /* version */
4694 if (meta->idx_string_wide)
4696 if (meta->idx_guid_wide)
4698 if (meta->idx_blob_wide)
4701 *p++ = 1; /* reserved */
4702 int64val = (guint64*)p;
4703 *int64val++ = GUINT64_TO_LE (valid_mask);
4704 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4706 int32val = (guint32*)p;
4707 for (i = 0; i < MONO_TABLE_NUM; i++){
4708 if (meta->tables [i].rows == 0)
4710 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4712 p = (unsigned char*)int32val;
4714 /* sort the tables that still need sorting */
4715 table = &assembly->tables [MONO_TABLE_CONSTANT];
4717 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4718 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4720 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4721 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4723 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4724 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4726 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4727 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4729 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4730 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4731 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4733 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4734 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4736 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4738 /* compress the tables */
4739 for (i = 0; i < MONO_TABLE_NUM; i++){
4742 guint32 bitfield = meta->tables [i].size_bitfield;
4743 if (!meta->tables [i].rows)
4745 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4746 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4747 meta->tables [i].base = (char*)p;
4748 for (row = 1; row <= meta->tables [i].rows; ++row) {
4749 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4750 for (col = 0; col < assembly->tables [i].columns; ++col) {
4751 switch (mono_metadata_table_size (bitfield, col)) {
4753 *p++ = values [col];
4756 *p++ = values [col] & 0xff;
4757 *p++ = (values [col] >> 8) & 0xff;
4760 *p++ = values [col] & 0xff;
4761 *p++ = (values [col] >> 8) & 0xff;
4762 *p++ = (values [col] >> 16) & 0xff;
4763 *p++ = (values [col] >> 24) & 0xff;
4766 g_assert_not_reached ();
4770 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4773 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4774 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4775 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4776 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4777 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4779 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4785 * Some tables in metadata need to be sorted according to some criteria, but
4786 * when methods and fields are first created with reflection, they may be assigned a token
4787 * that doesn't correspond to the final token they will get assigned after the sorting.
4788 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4789 * with the reflection objects that represent them. Once all the tables are set up, the
4790 * reflection objects will contains the correct table index. fixup_method() will fixup the
4791 * tokens for the method with ILGenerator @ilgen.
4794 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4796 guint32 code_idx = GPOINTER_TO_UINT (value);
4797 MonoReflectionILTokenInfo *iltoken;
4798 MonoReflectionFieldBuilder *field;
4799 MonoReflectionCtorBuilder *ctor;
4800 MonoReflectionMethodBuilder *method;
4801 MonoReflectionTypeBuilder *tb;
4802 MonoReflectionArrayMethod *am;
4804 unsigned char *target;
4806 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4807 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4808 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4809 switch (target [3]) {
4810 case MONO_TABLE_FIELD:
4811 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4812 field = (MonoReflectionFieldBuilder *)iltoken->member;
4813 idx = field->table_idx;
4814 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4815 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4816 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4818 g_assert_not_reached ();
4821 case MONO_TABLE_METHOD:
4822 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4823 method = (MonoReflectionMethodBuilder *)iltoken->member;
4824 idx = method->table_idx;
4825 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4826 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4827 idx = ctor->table_idx;
4828 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4829 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4830 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4831 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4833 g_assert_not_reached ();
4836 case MONO_TABLE_TYPEDEF:
4837 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4838 g_assert_not_reached ();
4839 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4840 idx = tb->table_idx;
4842 case MONO_TABLE_MEMBERREF:
4843 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4844 am = (MonoReflectionArrayMethod*)iltoken->member;
4845 idx = am->table_idx;
4846 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4847 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4848 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4849 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4850 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4851 g_assert (m->klass->generic_class || m->klass->generic_container);
4853 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4855 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4856 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4857 g_assert (is_field_on_inst (f));
4859 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4860 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4862 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4864 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4866 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4869 g_assert_not_reached ();
4872 case MONO_TABLE_METHODSPEC:
4873 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4874 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4875 g_assert (mono_method_signature (m)->generic_param_count);
4877 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4879 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4882 g_assert_not_reached ();
4886 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4888 target [0] = idx & 0xff;
4889 target [1] = (idx >> 8) & 0xff;
4890 target [2] = (idx >> 16) & 0xff;
4897 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4898 * value is not known when the table is emitted.
4901 fixup_cattrs (MonoDynamicImage *assembly)
4903 MonoDynamicTable *table;
4905 guint32 type, i, idx, token;
4908 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4910 for (i = 0; i < table->rows; ++i) {
4911 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4913 type = values [MONO_CUSTOM_ATTR_TYPE];
4914 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4915 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4916 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4917 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4920 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4921 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4922 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4923 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4924 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4925 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4926 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4927 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4934 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4936 MonoDynamicTable *table;
4939 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4941 alloc_table (table, table->rows);
4942 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4943 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4944 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4945 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4946 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4951 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4953 MonoDynamicTable *table;
4957 char *b = blob_size;
4959 guint32 idx, offset;
4961 if (rsrc->filename) {
4962 name = mono_string_to_utf8 (rsrc->filename);
4963 sname = g_path_get_basename (name);
4965 table = &assembly->tables [MONO_TABLE_FILE];
4967 alloc_table (table, table->rows);
4968 values = table->values + table->next_idx * MONO_FILE_SIZE;
4969 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4970 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4973 mono_sha1_get_digest_from_file (name, hash);
4974 mono_metadata_encode_value (20, b, &b);
4975 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4976 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4978 idx = table->next_idx++;
4980 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4986 data = mono_array_addr (rsrc->data, char, 0);
4987 len = mono_array_length (rsrc->data);
4993 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4994 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4995 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4996 mono_image_add_stream_data (&assembly->resources, data, len);
5000 * The entry should be emitted into the MANIFESTRESOURCE table of
5001 * the main module, but that needs to reference the FILE table
5002 * which isn't emitted yet.
5009 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5013 set_version_from_string (MonoString *version, guint32 *values)
5015 gchar *ver, *p, *str;
5018 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5019 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5020 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5021 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5024 ver = str = mono_string_to_utf8 (version);
5025 for (i = 0; i < 4; ++i) {
5026 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5032 /* handle Revision and Build */
5042 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5046 char *b = blob_size;
5051 len = mono_array_length (pkey);
5052 mono_metadata_encode_value (len, b, &b);
5053 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5054 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5056 assembly->public_key = (guint8 *)g_malloc (len);
5057 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5058 assembly->public_key_len = len;
5060 /* Special case: check for ECMA key (16 bytes) */
5061 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5062 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5063 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5064 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5065 /* minimum key size (in 2.0) is 384 bits */
5066 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5068 /* FIXME - verifier */
5069 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5070 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5072 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5078 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5080 MonoDynamicTable *table;
5081 MonoDynamicImage *assembly;
5082 MonoReflectionAssemblyBuilder *assemblyb;
5086 guint32 module_index;
5088 mono_error_init (error);
5090 assemblyb = moduleb->assemblyb;
5091 assembly = moduleb->dynamic_image;
5092 domain = mono_object_domain (assemblyb);
5094 /* Emit ASSEMBLY table */
5095 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5096 alloc_table (table, 1);
5097 values = table->values + MONO_ASSEMBLY_SIZE;
5098 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5099 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5100 if (assemblyb->culture) {
5101 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5103 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5105 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5106 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5107 set_version_from_string (assemblyb->version, values);
5109 /* Emit FILE + EXPORTED_TYPE table */
5111 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5113 MonoReflectionModuleBuilder *file_module =
5114 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5115 if (file_module != moduleb) {
5116 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5118 if (file_module->types) {
5119 for (j = 0; j < file_module->num_types; ++j) {
5120 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5121 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5122 return_if_nok (error);
5127 if (assemblyb->loaded_modules) {
5128 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5129 MonoReflectionModule *file_module =
5130 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5131 mono_image_fill_file_table (domain, file_module, assembly);
5133 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5136 if (assemblyb->type_forwarders)
5137 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5139 /* Emit MANIFESTRESOURCE table */
5141 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5143 MonoReflectionModuleBuilder *file_module =
5144 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5145 /* The table for the main module is emitted later */
5146 if (file_module != moduleb) {
5148 if (file_module->resources) {
5149 int len = mono_array_length (file_module->resources);
5150 for (j = 0; j < len; ++j) {
5151 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5152 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5159 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5162 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5163 * for the modulebuilder @moduleb.
5164 * At the end of the process, method and field tokens are fixed up and the
5165 * on-disk compressed metadata representation is created.
5166 * Return TRUE on success, or FALSE on failure and sets @error
5169 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5171 MonoDynamicTable *table;
5172 MonoDynamicImage *assembly;
5173 MonoReflectionAssemblyBuilder *assemblyb;
5179 mono_error_init (error);
5181 assemblyb = moduleb->assemblyb;
5182 assembly = moduleb->dynamic_image;
5183 domain = mono_object_domain (assemblyb);
5185 if (assembly->text_rva)
5188 assembly->text_rva = START_TEXT_RVA;
5190 if (moduleb->is_main) {
5191 mono_image_emit_manifest (moduleb, error);
5192 return_val_if_nok (error, FALSE);
5195 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5196 table->rows = 1; /* .<Module> */
5198 alloc_table (table, table->rows);
5200 * Set the first entry.
5202 values = table->values + table->columns;
5203 values [MONO_TYPEDEF_FLAGS] = 0;
5204 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5205 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5206 values [MONO_TYPEDEF_EXTENDS] = 0;
5207 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5208 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5211 * handle global methods
5212 * FIXME: test what to do when global methods are defined in multiple modules.
5214 if (moduleb->global_methods) {
5215 table = &assembly->tables [MONO_TABLE_METHOD];
5216 table->rows += mono_array_length (moduleb->global_methods);
5217 alloc_table (table, table->rows);
5218 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5219 if (!mono_image_get_method_info (
5220 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5224 if (moduleb->global_fields) {
5225 table = &assembly->tables [MONO_TABLE_FIELD];
5226 table->rows += mono_array_length (moduleb->global_fields);
5227 alloc_table (table, table->rows);
5228 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5229 mono_image_get_field_info (
5230 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5237 table = &assembly->tables [MONO_TABLE_MODULE];
5238 alloc_table (table, 1);
5239 mono_image_fill_module_table (domain, moduleb, assembly);
5241 /* Collect all types into a list sorted by their table_idx */
5242 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5245 for (i = 0; i < moduleb->num_types; ++i) {
5246 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5247 collect_types (&types, type);
5250 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5251 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5252 table->rows += mono_ptr_array_size (types);
5253 alloc_table (table, table->rows);
5256 * Emit type names + namespaces at one place inside the string heap,
5257 * so load_class_names () needs to touch fewer pages.
5259 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5260 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5261 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5263 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5264 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5265 string_heap_insert_mstring (&assembly->sheap, tb->name);
5268 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5269 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5270 if (!mono_image_get_type_info (domain, type, assembly, error))
5275 * table->rows is already set above and in mono_image_fill_module_table.
5277 /* add all the custom attributes at the end, once all the indexes are stable */
5278 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5281 /* CAS assembly permissions */
5282 if (assemblyb->permissions_minimum)
5283 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5284 if (assemblyb->permissions_optional)
5285 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5286 if (assemblyb->permissions_refused)
5287 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5289 if (!module_add_cattrs (assembly, moduleb, error))
5293 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5295 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5296 * the final tokens and don't need another fixup pass. */
5298 if (moduleb->global_methods) {
5299 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5300 MonoReflectionMethodBuilder *mb = mono_array_get (
5301 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5302 if (!mono_image_add_methodimpl (assembly, mb, error))
5307 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5308 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5309 if (type->methods) {
5310 for (j = 0; j < type->num_methods; ++j) {
5311 MonoReflectionMethodBuilder *mb = mono_array_get (
5312 type->methods, MonoReflectionMethodBuilder*, j);
5314 if (!mono_image_add_methodimpl (assembly, mb, error))
5320 fixup_cattrs (assembly);
5323 mono_ptr_array_destroy (types);
5326 return mono_error_ok (error);
5329 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5332 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5334 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5337 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5341 guint32 import_lookup_table;
5345 guint32 import_address_table_rva;
5353 #ifndef DISABLE_REFLECTION_EMIT
5356 * mono_image_insert_string:
5357 * @module: module builder object
5360 * Insert @str into the user string stream of @module.
5363 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5365 MonoDynamicImage *assembly;
5370 if (!module->dynamic_image)
5371 mono_image_module_basic_init (module);
5373 assembly = module->dynamic_image;
5375 if (assembly->save) {
5376 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5377 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5378 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5380 char *swapped = g_malloc (2 * mono_string_length (str));
5381 const char *p = (const char*)mono_string_chars (str);
5383 swap_with_size (swapped, p, 2, mono_string_length (str));
5384 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5388 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5390 mono_image_add_stream_data (&assembly->us, "", 1);
5392 idx = assembly->us.index ++;
5395 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5397 return MONO_TOKEN_STRING | idx;
5401 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5405 MonoMethodSignature *sig;
5407 mono_error_init (error);
5409 klass = obj->vtable->klass;
5410 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5411 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5412 MonoMethodSignature *old;
5413 guint32 sig_token, parent;
5416 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5418 nargs = mono_array_length (opt_param_types);
5419 old = mono_method_signature (method);
5420 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5422 sig->hasthis = old->hasthis;
5423 sig->explicit_this = old->explicit_this;
5424 sig->call_convention = old->call_convention;
5425 sig->generic_param_count = old->generic_param_count;
5426 sig->param_count = old->param_count + nargs;
5427 sig->sentinelpos = old->param_count;
5428 sig->ret = old->ret;
5430 for (i = 0; i < old->param_count; i++)
5431 sig->params [i] = old->params [i];
5433 for (i = 0; i < nargs; i++) {
5434 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5435 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5436 if (!is_ok (error)) goto fail;
5439 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5440 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5441 parent >>= MONO_TYPEDEFORREF_BITS;
5443 parent <<= MONO_MEMBERREF_PARENT_BITS;
5444 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5446 sig_token = method_encode_signature (assembly, sig);
5447 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5448 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5449 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5450 ReflectionMethodBuilder rmb;
5451 guint32 parent, sig_token;
5452 int nopt_args, nparams, ngparams, i;
5454 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5457 rmb.opt_types = opt_param_types;
5458 nopt_args = mono_array_length (opt_param_types);
5460 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5461 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5462 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5464 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5465 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5466 sig->call_convention = rmb.call_conv;
5467 sig->generic_param_count = ngparams;
5468 sig->param_count = nparams + nopt_args;
5469 sig->sentinelpos = nparams;
5470 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5471 if (!is_ok (error)) goto fail;
5473 for (i = 0; i < nparams; i++) {
5474 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5475 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5476 if (!is_ok (error)) goto fail;
5479 for (i = 0; i < nopt_args; i++) {
5480 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5481 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5482 if (!is_ok (error)) goto fail;
5485 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5489 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5490 if (!mono_error_ok (error))
5492 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5494 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5495 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5497 char *name = mono_string_to_utf8 (rmb.name);
5498 token = mono_image_get_varargs_method_token (
5499 assembly, parent, name, sig_token);
5502 g_error ("requested method token for %s\n", klass->name);
5505 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5506 register_dyn_token (assembly, token, obj);
5509 g_assert (!mono_error_ok (error));
5514 * mono_image_create_token:
5515 * @assembly: a dynamic assembly
5517 * @register_token: Whenever to register the token in the assembly->tokens hash.
5519 * Get a token to insert in the IL code stream for the given MemberInfo.
5520 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5521 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5525 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5526 gboolean create_open_instance, gboolean register_token,
5532 mono_error_init (error);
5534 klass = obj->vtable->klass;
5536 /* Check for user defined reflection objects */
5537 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5538 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5539 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5543 if (strcmp (klass->name, "MethodBuilder") == 0) {
5544 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5545 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5547 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5548 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5550 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5551 if (!mono_error_ok (error))
5554 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5555 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5556 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5557 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5559 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5560 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5562 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5563 if (!mono_error_ok (error))
5566 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5567 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5568 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5569 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5570 if (tb->generic_params) {
5571 token = mono_image_get_generic_field_token (assembly, fb, error);
5572 return_val_if_nok (error, 0);
5574 if (tb->module->dynamic_image == assembly) {
5575 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5577 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5580 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5581 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5582 if (create_open_instance && tb->generic_params) {
5584 init_type_builder_generics (obj);
5585 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5586 return_val_if_nok (error, 0);
5587 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5588 token = mono_metadata_token_from_dor (token);
5589 } else if (tb->module->dynamic_image == assembly) {
5590 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5593 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594 return_val_if_nok (error, 0);
5595 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5597 } else if (strcmp (klass->name, "MonoType") == 0) {
5598 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5599 return_val_if_nok (error, 0);
5600 MonoClass *mc = mono_class_from_mono_type (type);
5601 token = mono_metadata_token_from_dor (
5602 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5603 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5604 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5605 return_val_if_nok (error, 0);
5606 token = mono_metadata_token_from_dor (
5607 mono_image_typedef_or_ref (assembly, type));
5608 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5609 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5610 return_val_if_nok (error, 0);
5611 token = mono_metadata_token_from_dor (
5612 mono_image_typedef_or_ref (assembly, type));
5613 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5614 strcmp (klass->name, "MonoMethod") == 0 ||
5615 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5616 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5617 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5618 if (m->method->is_inflated) {
5619 if (create_open_instance)
5620 token = mono_image_get_methodspec_token (assembly, m->method);
5622 token = mono_image_get_inflated_method_token (assembly, m->method);
5623 } else if ((m->method->klass->image == &assembly->image) &&
5624 !m->method->klass->generic_class) {
5625 static guint32 method_table_idx = 0xffffff;
5626 if (m->method->klass->wastypebuilder) {
5627 /* we use the same token as the one that was assigned
5628 * to the Methodbuilder.
5629 * FIXME: do the equivalent for Fields.
5631 token = m->method->token;
5634 * Each token should have a unique index, but the indexes are
5635 * assigned by managed code, so we don't know about them. An
5636 * easy solution is to count backwards...
5638 method_table_idx --;
5639 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5642 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5644 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5645 } else if (strcmp (klass->name, "MonoField") == 0) {
5646 MonoReflectionField *f = (MonoReflectionField *)obj;
5647 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5648 static guint32 field_table_idx = 0xffffff;
5650 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5652 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5654 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5655 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5656 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5657 token = mono_image_get_array_token (assembly, m, error);
5658 return_val_if_nok (error, 0);
5659 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5660 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5661 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5662 return_val_if_nok (error, 0);
5663 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5664 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5665 return_val_if_nok (error, 0);
5666 token = mono_metadata_token_from_dor (
5667 mono_image_typedef_or_ref (assembly, type));
5668 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5669 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5670 token = mono_image_get_field_on_inst_token (assembly, f, error);
5671 return_val_if_nok (error, 0);
5672 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5673 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5674 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5675 if (!mono_error_ok (error))
5677 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5678 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5679 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5680 if (!mono_error_ok (error))
5682 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5683 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5684 return_val_if_nok (error, 0);
5685 token = mono_metadata_token_from_dor (
5686 mono_image_typedef_or_ref (assembly, type));
5688 g_error ("requested token for %s\n", klass->name);
5692 mono_image_register_token (assembly, token, obj);
5698 * mono_image_register_token:
5700 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5701 * the Module.ResolveXXXToken () methods to work.
5704 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5708 dynamic_image_lock (assembly);
5709 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5711 /* There could be multiple MethodInfo objects with the same token */
5712 //g_assert (prev == obj);
5714 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5716 dynamic_image_unlock (assembly);
5719 static MonoDynamicImage*
5720 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5722 static const guchar entrycode [16] = {0xff, 0x25, 0};
5723 MonoDynamicImage *image;
5726 const char *version;
5728 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5729 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5731 version = mono_get_runtime_info ()->runtime_version;
5734 /* The MonoGHashTable's need GC tracking */
5735 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5737 image = g_new0 (MonoDynamicImage, 1);
5740 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5742 /*g_print ("created image %p\n", image);*/
5743 /* keep in sync with image.c */
5744 image->image.name = assembly_name;
5745 image->image.assembly_name = image->image.name; /* they may be different */
5746 image->image.module_name = module_name;
5747 image->image.version = g_strdup (version);
5748 image->image.md_version_major = 1;
5749 image->image.md_version_minor = 1;
5750 image->image.dynamic = TRUE;
5752 image->image.references = g_new0 (MonoAssembly*, 1);
5753 image->image.references [0] = NULL;
5755 mono_image_init (&image->image);
5757 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");
5758 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5759 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5760 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5761 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5762 image->handleref = g_hash_table_new (NULL, NULL);
5763 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");
5764 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5765 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");
5766 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");
5767 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5768 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5769 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5770 image->gen_params = g_ptr_array_new ();
5771 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5773 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5774 string_heap_init (&image->sheap);
5775 mono_image_add_stream_data (&image->us, "", 1);
5776 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5777 /* import tables... */
5778 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5779 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5780 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5781 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5782 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5783 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5784 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5785 stream_data_align (&image->code);
5787 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5789 for (i=0; i < MONO_TABLE_NUM; ++i) {
5790 image->tables [i].next_idx = 1;
5791 image->tables [i].columns = table_sizes [i];
5794 image->image.assembly = (MonoAssembly*)assembly;
5795 image->run = assembly->run;
5796 image->save = assembly->save;
5797 image->pe_kind = 0x1; /* ILOnly */
5798 image->machine = 0x14c; /* I386 */
5800 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5802 dynamic_images_lock ();
5804 if (!dynamic_images)
5805 dynamic_images = g_ptr_array_new ();
5807 g_ptr_array_add (dynamic_images, image);
5809 dynamic_images_unlock ();
5816 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5822 release_hashtable (MonoGHashTable **hash)
5825 mono_g_hash_table_destroy (*hash);
5831 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5833 release_hashtable (&image->token_fixups);
5834 release_hashtable (&image->handleref_managed);
5835 release_hashtable (&image->tokens);
5836 release_hashtable (&image->remapped_tokens);
5837 release_hashtable (&image->generic_def_objects);
5838 release_hashtable (&image->methodspec);
5841 // Free dynamic image pass one: Free resources but not image itself
5843 mono_dynamic_image_free (MonoDynamicImage *image)
5845 MonoDynamicImage *di = image;
5850 mono_g_hash_table_destroy (di->methodspec);
5852 g_hash_table_destroy (di->typespec);
5854 g_hash_table_destroy (di->typeref);
5856 g_hash_table_destroy (di->handleref);
5857 if (di->handleref_managed)
5858 mono_g_hash_table_destroy (di->handleref_managed);
5860 mono_g_hash_table_destroy (di->tokens);
5861 if (di->remapped_tokens)
5862 mono_g_hash_table_destroy (di->remapped_tokens);
5863 if (di->generic_def_objects)
5864 mono_g_hash_table_destroy (di->generic_def_objects);
5865 if (di->blob_cache) {
5866 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5867 g_hash_table_destroy (di->blob_cache);
5869 if (di->standalonesig_cache)
5870 g_hash_table_destroy (di->standalonesig_cache);
5871 for (list = di->array_methods; list; list = list->next) {
5872 ArrayMethod *am = (ArrayMethod *)list->data;
5877 g_list_free (di->array_methods);
5878 if (di->gen_params) {
5879 for (i = 0; i < di->gen_params->len; i++) {
5880 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5881 mono_gc_deregister_root ((char*) &entry->gparam);
5884 g_ptr_array_free (di->gen_params, TRUE);
5886 if (di->token_fixups)
5887 mono_g_hash_table_destroy (di->token_fixups);
5888 if (di->method_to_table_idx)
5889 g_hash_table_destroy (di->method_to_table_idx);
5890 if (di->field_to_table_idx)
5891 g_hash_table_destroy (di->field_to_table_idx);
5892 if (di->method_aux_hash)
5893 g_hash_table_destroy (di->method_aux_hash);
5894 if (di->vararg_aux_hash)
5895 g_hash_table_destroy (di->vararg_aux_hash);
5896 g_free (di->strong_name);
5897 g_free (di->win32_res);
5899 g_free (di->public_key);
5901 /*g_print ("string heap destroy for image %p\n", di);*/
5902 mono_dynamic_stream_reset (&di->sheap);
5903 mono_dynamic_stream_reset (&di->code);
5904 mono_dynamic_stream_reset (&di->resources);
5905 mono_dynamic_stream_reset (&di->us);
5906 mono_dynamic_stream_reset (&di->blob);
5907 mono_dynamic_stream_reset (&di->tstream);
5908 mono_dynamic_stream_reset (&di->guid);
5909 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5910 g_free (di->tables [i].values);
5913 dynamic_images_lock ();
5916 g_ptr_array_remove (dynamic_images, di);
5918 dynamic_images_unlock ();
5921 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5923 mono_dynamic_image_free_image (MonoDynamicImage *image)
5925 /* See create_dynamic_mono_image () */
5927 /* Allocated using GC_MALLOC */
5933 #ifndef DISABLE_REFLECTION_EMIT
5936 * mono_image_basic_init:
5937 * @assembly: an assembly builder object
5939 * Create the MonoImage that represents the assembly builder and setup some
5940 * of the helper hash table and the basic metadata streams.
5943 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5945 MonoDynamicAssembly *assembly;
5946 MonoDynamicImage *image;
5947 MonoDomain *domain = mono_object_domain (assemblyb);
5949 if (assemblyb->dynamic_assembly)
5953 /* assembly->assembly.image might be GC allocated */
5954 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5956 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5959 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5961 assembly->assembly.ref_count = 1;
5962 assembly->assembly.dynamic = TRUE;
5963 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5964 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5965 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5966 if (assemblyb->culture)
5967 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5969 assembly->assembly.aname.culture = g_strdup ("");
5971 if (assemblyb->version) {
5972 char *vstr = mono_string_to_utf8 (assemblyb->version);
5973 char **version = g_strsplit (vstr, ".", 4);
5974 char **parts = version;
5975 assembly->assembly.aname.major = atoi (*parts++);
5976 assembly->assembly.aname.minor = atoi (*parts++);
5977 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5978 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5980 g_strfreev (version);
5983 assembly->assembly.aname.major = 0;
5984 assembly->assembly.aname.minor = 0;
5985 assembly->assembly.aname.build = 0;
5986 assembly->assembly.aname.revision = 0;
5989 assembly->run = assemblyb->access != 2;
5990 assembly->save = assemblyb->access != 1;
5991 assembly->domain = domain;
5993 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5994 image->initial_image = TRUE;
5995 assembly->assembly.aname.name = image->image.name;
5996 assembly->assembly.image = &image->image;
5997 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5998 /* -1 to correct for the trailing NULL byte */
5999 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6000 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6002 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6005 mono_domain_assemblies_lock (domain);
6006 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6007 mono_domain_assemblies_unlock (domain);
6009 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6011 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6013 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6016 #endif /* !DISABLE_REFLECTION_EMIT */
6018 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6021 calc_section_size (MonoDynamicImage *assembly)
6025 /* alignment constraints */
6026 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6027 g_assert ((assembly->code.index % 4) == 0);
6028 assembly->meta_size += 3;
6029 assembly->meta_size &= ~3;
6030 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6031 g_assert ((assembly->resources.index % 4) == 0);
6033 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6034 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6037 if (assembly->win32_res) {
6038 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6040 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6041 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6045 assembly->sections [MONO_SECTION_RELOC].size = 12;
6046 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6056 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6060 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6062 ResTreeNode *t1 = (ResTreeNode*)a;
6063 ResTreeNode *t2 = (ResTreeNode*)b;
6065 return t1->id - t2->id;
6069 * resource_tree_create:
6071 * Organize the resources into a resource tree.
6073 static ResTreeNode *
6074 resource_tree_create (MonoArray *win32_resources)
6076 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6080 tree = g_new0 (ResTreeNode, 1);
6082 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6083 MonoReflectionWin32Resource *win32_res =
6084 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6088 /* FIXME: BUG: this stores managed references in unmanaged memory */
6089 lang_node = g_new0 (ResTreeNode, 1);
6090 lang_node->id = win32_res->lang_id;
6091 lang_node->win32_res = win32_res;
6093 /* Create type node if neccesary */
6095 for (l = tree->children; l; l = l->next)
6096 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6097 type_node = (ResTreeNode*)l->data;
6102 type_node = g_new0 (ResTreeNode, 1);
6103 type_node->id = win32_res->res_type;
6106 * The resource types have to be sorted otherwise
6107 * Windows Explorer can't display the version information.
6109 tree->children = g_slist_insert_sorted (tree->children,
6110 type_node, resource_tree_compare_by_id);
6113 /* Create res node if neccesary */
6115 for (l = type_node->children; l; l = l->next)
6116 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6117 res_node = (ResTreeNode*)l->data;
6122 res_node = g_new0 (ResTreeNode, 1);
6123 res_node->id = win32_res->res_id;
6124 type_node->children = g_slist_append (type_node->children, res_node);
6127 res_node->children = g_slist_append (res_node->children, lang_node);
6134 * resource_tree_encode:
6136 * Encode the resource tree into the format used in the PE file.
6139 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6142 MonoPEResourceDir dir;
6143 MonoPEResourceDirEntry dir_entry;
6144 MonoPEResourceDataEntry data_entry;
6146 guint32 res_id_entries;
6149 * For the format of the resource directory, see the article
6150 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6154 memset (&dir, 0, sizeof (dir));
6155 memset (&dir_entry, 0, sizeof (dir_entry));
6156 memset (&data_entry, 0, sizeof (data_entry));
6158 g_assert (sizeof (dir) == 16);
6159 g_assert (sizeof (dir_entry) == 8);
6160 g_assert (sizeof (data_entry) == 16);
6162 node->offset = p - begin;
6164 /* IMAGE_RESOURCE_DIRECTORY */
6165 res_id_entries = g_slist_length (node->children);
6166 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6168 memcpy (p, &dir, sizeof (dir));
6171 /* Reserve space for entries */
6173 p += sizeof (dir_entry) * res_id_entries;
6175 /* Write children */
6176 for (l = node->children; l; l = l->next) {
6177 ResTreeNode *child = (ResTreeNode*)l->data;
6179 if (child->win32_res) {
6182 child->offset = p - begin;
6184 /* IMAGE_RESOURCE_DATA_ENTRY */
6185 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6186 size = mono_array_length (child->win32_res->res_data);
6187 data_entry.rde_size = GUINT32_TO_LE (size);
6189 memcpy (p, &data_entry, sizeof (data_entry));
6190 p += sizeof (data_entry);
6192 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6195 resource_tree_encode (child, begin, p, &p);
6199 /* IMAGE_RESOURCE_ENTRY */
6200 for (l = node->children; l; l = l->next) {
6201 ResTreeNode *child = (ResTreeNode*)l->data;
6203 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6204 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6206 memcpy (entries, &dir_entry, sizeof (dir_entry));
6207 entries += sizeof (dir_entry);
6214 resource_tree_free (ResTreeNode * node)
6217 for (list = node->children; list; list = list->next)
6218 resource_tree_free ((ResTreeNode*)list->data);
6219 g_slist_free(node->children);
6224 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6229 MonoReflectionWin32Resource *win32_res;
6232 if (!assemblyb->win32_resources)
6236 * Resources are stored in a three level tree inside the PE file.
6237 * - level one contains a node for each type of resource
6238 * - level two contains a node for each resource
6239 * - level three contains a node for each instance of a resource for a
6240 * specific language.
6243 tree = resource_tree_create (assemblyb->win32_resources);
6245 /* Estimate the size of the encoded tree */
6247 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6248 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6249 size += mono_array_length (win32_res->res_data);
6251 /* Directory structure */
6252 size += mono_array_length (assemblyb->win32_resources) * 256;
6253 p = buf = (char *)g_malloc (size);
6255 resource_tree_encode (tree, p, p, &p);
6257 g_assert (p - buf <= size);
6259 assembly->win32_res = (char *)g_malloc (p - buf);
6260 assembly->win32_res_size = p - buf;
6261 memcpy (assembly->win32_res, buf, p - buf);
6264 resource_tree_free (tree);
6268 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6270 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6273 p += sizeof (MonoPEResourceDir);
6274 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6275 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6276 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6277 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6278 fixup_resource_directory (res_section, child, rva);
6280 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6281 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6284 p += sizeof (MonoPEResourceDirEntry);
6289 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6292 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6293 g_error ("WriteFile returned %d\n", GetLastError ());
6297 * mono_image_create_pefile:
6298 * @mb: a module builder object
6300 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6301 * assembly->pefile where it can be easily retrieved later in chunks.
6304 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6306 MonoMSDOSHeader *msdos;
6307 MonoDotNetHeader *header;
6308 MonoSectionTable *section;
6309 MonoCLIHeader *cli_header;
6310 guint32 size, image_size, virtual_base, text_offset;
6311 guint32 header_start, section_start, file_offset, virtual_offset;
6312 MonoDynamicImage *assembly;
6313 MonoReflectionAssemblyBuilder *assemblyb;
6314 MonoDynamicStream pefile_stream = {0};
6315 MonoDynamicStream *pefile = &pefile_stream;
6317 guint32 *rva, value;
6319 static const unsigned char msheader[] = {
6320 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6321 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6324 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6325 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6326 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6327 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6330 mono_error_init (error);
6332 assemblyb = mb->assemblyb;
6334 mono_image_basic_init (assemblyb);
6335 assembly = mb->dynamic_image;
6337 assembly->pe_kind = assemblyb->pe_kind;
6338 assembly->machine = assemblyb->machine;
6339 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6340 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6342 if (!mono_image_build_metadata (mb, error))
6346 if (mb->is_main && assemblyb->resources) {
6347 int len = mono_array_length (assemblyb->resources);
6348 for (i = 0; i < len; ++i)
6349 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6352 if (mb->resources) {
6353 int len = mono_array_length (mb->resources);
6354 for (i = 0; i < len; ++i)
6355 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6358 if (!build_compressed_metadata (assembly, error))
6362 assembly_add_win32_resources (assembly, assemblyb);
6364 nsections = calc_section_size (assembly);
6366 /* The DOS header and stub */
6367 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6368 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6370 /* the dotnet header */
6371 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6373 /* the section tables */
6374 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6376 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6377 virtual_offset = VIRT_ALIGN;
6380 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6381 if (!assembly->sections [i].size)
6384 file_offset += FILE_ALIGN - 1;
6385 file_offset &= ~(FILE_ALIGN - 1);
6386 virtual_offset += VIRT_ALIGN - 1;
6387 virtual_offset &= ~(VIRT_ALIGN - 1);
6389 assembly->sections [i].offset = file_offset;
6390 assembly->sections [i].rva = virtual_offset;
6392 file_offset += assembly->sections [i].size;
6393 virtual_offset += assembly->sections [i].size;
6394 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6397 file_offset += FILE_ALIGN - 1;
6398 file_offset &= ~(FILE_ALIGN - 1);
6400 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6402 /* back-patch info */
6403 msdos = (MonoMSDOSHeader*)pefile->data;
6404 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6406 header = (MonoDotNetHeader*)(pefile->data + header_start);
6407 header->pesig [0] = 'P';
6408 header->pesig [1] = 'E';
6410 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6411 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6412 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6413 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6414 if (assemblyb->pekind == 1) {
6416 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6419 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6422 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6424 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6425 header->pe.pe_major = 6;
6426 header->pe.pe_minor = 0;
6427 size = assembly->sections [MONO_SECTION_TEXT].size;
6428 size += FILE_ALIGN - 1;
6429 size &= ~(FILE_ALIGN - 1);
6430 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6431 size = assembly->sections [MONO_SECTION_RSRC].size;
6432 size += FILE_ALIGN - 1;
6433 size &= ~(FILE_ALIGN - 1);
6434 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6435 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6436 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6437 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6438 /* pe_rva_entry_point always at the beginning of the text section */
6439 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6441 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6442 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6443 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6444 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6445 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6446 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6447 size = section_start;
6448 size += FILE_ALIGN - 1;
6449 size &= ~(FILE_ALIGN - 1);
6450 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6452 size += VIRT_ALIGN - 1;
6453 size &= ~(VIRT_ALIGN - 1);
6454 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6457 // Translate the PEFileKind value to the value expected by the Windows loader
6463 // PEFileKinds.Dll == 1
6464 // PEFileKinds.ConsoleApplication == 2
6465 // PEFileKinds.WindowApplication == 3
6468 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6469 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6471 if (assemblyb->pekind == 3)
6476 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6478 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6479 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6480 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6481 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6482 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6483 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6485 /* fill data directory entries */
6487 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6488 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6490 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6491 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6493 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6494 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6495 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6496 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6497 /* patch entrypoint name */
6498 if (assemblyb->pekind == 1)
6499 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6501 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6502 /* patch imported function RVA name */
6503 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6504 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6506 /* the import table */
6507 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6508 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6509 /* patch imported dll RVA name and other entries in the dir */
6510 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6511 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6512 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6513 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6514 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6515 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6517 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6518 value = (assembly->text_rva + assembly->imp_names_offset);
6519 *p++ = (value) & 0xff;
6520 *p++ = (value >> 8) & (0xff);
6521 *p++ = (value >> 16) & (0xff);
6522 *p++ = (value >> 24) & (0xff);
6524 /* the CLI header info */
6525 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6526 cli_header->ch_size = GUINT32_FROM_LE (72);
6527 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6528 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6529 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6530 if (assemblyb->entry_point) {
6531 guint32 table_idx = 0;
6532 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6533 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6534 table_idx = methodb->table_idx;
6536 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6538 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6540 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6542 /* The embedded managed resources */
6543 text_offset = assembly->text_rva + assembly->code.index;
6544 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6545 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6546 text_offset += assembly->resources.index;
6547 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6548 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6549 text_offset += assembly->meta_size;
6550 if (assembly->strong_name_size) {
6551 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6552 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6553 text_offset += assembly->strong_name_size;
6556 /* write the section tables and section content */
6557 section = (MonoSectionTable*)(pefile->data + section_start);
6558 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6559 static const char section_names [][7] = {
6560 ".text", ".rsrc", ".reloc"
6562 if (!assembly->sections [i].size)
6564 strcpy (section->st_name, section_names [i]);
6565 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6566 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6567 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6568 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6569 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6570 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6571 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6575 checked_write_file (file, pefile->data, pefile->index);
6577 mono_dynamic_stream_reset (pefile);
6579 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6580 if (!assembly->sections [i].size)
6583 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6584 g_error ("SetFilePointer returned %d\n", GetLastError ());
6587 case MONO_SECTION_TEXT:
6588 /* patch entry point */
6589 p = (guchar*)(assembly->code.data + 2);
6590 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6591 *p++ = (value) & 0xff;
6592 *p++ = (value >> 8) & 0xff;
6593 *p++ = (value >> 16) & 0xff;
6594 *p++ = (value >> 24) & 0xff;
6596 checked_write_file (file, assembly->code.data, assembly->code.index);
6597 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6598 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6599 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6602 g_free (assembly->image.raw_metadata);
6604 case MONO_SECTION_RELOC: {
6608 guint16 type_and_offset;
6612 g_assert (sizeof (reloc) == 12);
6614 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6615 reloc.block_size = GUINT32_FROM_LE (12);
6618 * the entrypoint is always at the start of the text section
6619 * 3 is IMAGE_REL_BASED_HIGHLOW
6620 * 2 is patch_size_rva - text_rva
6622 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6625 checked_write_file (file, &reloc, sizeof (reloc));
6629 case MONO_SECTION_RSRC:
6630 if (assembly->win32_res) {
6632 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6633 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6634 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6638 g_assert_not_reached ();
6642 /* check that the file is properly padded */
6643 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6644 g_error ("SetFilePointer returned %d\n", GetLastError ());
6645 if (! SetEndOfFile (file))
6646 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6648 mono_dynamic_stream_reset (&assembly->code);
6649 mono_dynamic_stream_reset (&assembly->us);
6650 mono_dynamic_stream_reset (&assembly->blob);
6651 mono_dynamic_stream_reset (&assembly->guid);
6652 mono_dynamic_stream_reset (&assembly->sheap);
6654 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6655 g_hash_table_destroy (assembly->blob_cache);
6656 assembly->blob_cache = NULL;
6661 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6664 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6666 g_assert_not_reached ();
6669 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6671 #ifndef DISABLE_REFLECTION_EMIT
6673 MonoReflectionModule *
6674 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6678 MonoImageOpenStatus status;
6679 MonoDynamicAssembly *assembly;
6680 guint32 module_count;
6681 MonoImage **new_modules;
6682 gboolean *new_modules_loaded;
6684 mono_error_init (error);
6686 name = mono_string_to_utf8 (fileName);
6688 image = mono_image_open (name, &status);
6690 if (status == MONO_IMAGE_ERROR_ERRNO)
6691 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6693 mono_error_set_bad_image_name (error, name, NULL);
6700 assembly = ab->dynamic_assembly;
6701 image->assembly = (MonoAssembly*)assembly;
6703 module_count = image->assembly->image->module_count;
6704 new_modules = g_new0 (MonoImage *, module_count + 1);
6705 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6707 if (image->assembly->image->modules)
6708 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6709 if (image->assembly->image->modules_loaded)
6710 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6711 new_modules [module_count] = image;
6712 new_modules_loaded [module_count] = TRUE;
6713 mono_image_addref (image);
6715 g_free (image->assembly->image->modules);
6716 image->assembly->image->modules = new_modules;
6717 image->assembly->image->modules_loaded = new_modules_loaded;
6718 image->assembly->image->module_count ++;
6720 mono_assembly_load_references (image, &status);
6722 mono_image_close (image);
6723 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6727 return mono_module_get_object_checked (mono_domain_get (), image, error);
6730 #endif /* DISABLE_REFLECTION_EMIT */
6733 * We need to return always the same object for MethodInfo, FieldInfo etc..
6734 * but we need to consider the reflected type.
6735 * type uses a different hash, since it uses custom hash/equal functions.
6740 MonoClass *refclass;
6744 reflected_equal (gconstpointer a, gconstpointer b) {
6745 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6746 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6748 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6752 reflected_hash (gconstpointer a) {
6753 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6754 return mono_aligned_addr_hash (ea->item);
6757 #define CHECK_OBJECT(t,p,k) \
6763 mono_domain_lock (domain); \
6764 if (!domain->refobject_hash) \
6765 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"); \
6766 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6767 mono_domain_unlock (domain); \
6770 mono_domain_unlock (domain); \
6773 #ifdef HAVE_BOEHM_GC
6774 /* ReflectedEntry doesn't need to be GC tracked */
6775 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6776 #define FREE_REFENTRY(entry) g_free ((entry))
6777 #define REFENTRY_REQUIRES_CLEANUP
6779 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6781 #define FREE_REFENTRY(entry)
6784 #define CACHE_OBJECT(t,p,o,k) \
6787 ReflectedEntry pe; \
6789 pe.refclass = (k); \
6790 mono_domain_lock (domain); \
6791 if (!domain->refobject_hash) \
6792 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"); \
6793 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6795 ReflectedEntry *e = ALLOC_REFENTRY; \
6797 e->refclass = (k); \
6798 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6801 mono_domain_unlock (domain); \
6806 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6808 mono_domain_lock (domain);
6809 if (domain->refobject_hash) {
6811 gpointer orig_pe, orig_value;
6814 pe.refclass = klass;
6815 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6816 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6817 FREE_REFENTRY (orig_pe);
6820 mono_domain_unlock (domain);
6823 #ifdef REFENTRY_REQUIRES_CLEANUP
6825 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6827 FREE_REFENTRY (key);
6832 mono_reflection_cleanup_domain (MonoDomain *domain)
6834 if (domain->refobject_hash) {
6835 /*let's avoid scanning the whole hashtable if not needed*/
6836 #ifdef REFENTRY_REQUIRES_CLEANUP
6837 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6839 mono_g_hash_table_destroy (domain->refobject_hash);
6840 domain->refobject_hash = NULL;
6844 #ifndef DISABLE_REFLECTION_EMIT
6846 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6848 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6852 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6854 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6858 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6860 MonoDynamicImage *image = moduleb->dynamic_image;
6861 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6865 MonoImage **new_modules;
6867 char *name, *fqname;
6869 * FIXME: we already created an image in mono_image_basic_init (), but
6870 * we don't know which module it belongs to, since that is only
6871 * determined at assembly save time.
6873 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6874 name = mono_string_to_utf8 (ab->name);
6875 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6876 if (!mono_error_ok (&error)) {
6878 mono_error_raise_exception (&error);
6880 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6882 moduleb->module.image = &image->image;
6883 moduleb->dynamic_image = image;
6884 register_module (mono_object_domain (moduleb), moduleb, image);
6886 /* register the module with the assembly */
6887 ass = ab->dynamic_assembly->assembly.image;
6888 module_count = ass->module_count;
6889 new_modules = g_new0 (MonoImage *, module_count + 1);
6892 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6893 new_modules [module_count] = &image->image;
6894 mono_image_addref (&image->image);
6896 g_free (ass->modules);
6897 ass->modules = new_modules;
6898 ass->module_count ++;
6903 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6905 MonoDynamicImage *image = moduleb->dynamic_image;
6907 g_assert (type->type);
6908 image->wrappers_type = mono_class_from_mono_type (type->type);
6914 * mono_assembly_get_object:
6915 * @domain: an app domain
6916 * @assembly: an assembly
6918 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6920 MonoReflectionAssembly*
6921 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6924 MonoReflectionAssembly *result;
6925 result = mono_assembly_get_object_checked (domain, assembly, &error);
6926 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6930 * mono_assembly_get_object_checked:
6931 * @domain: an app domain
6932 * @assembly: an assembly
6934 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6936 MonoReflectionAssembly*
6937 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6939 MonoReflectionAssembly *res;
6941 mono_error_init (error);
6943 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6944 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6947 res->assembly = assembly;
6949 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6954 MonoReflectionModule*
6955 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6958 MonoReflectionModule *result;
6959 result = mono_module_get_object_checked (domain, image, &error);
6960 mono_error_raise_exception (&error);
6964 MonoReflectionModule*
6965 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6967 MonoReflectionModule *res;
6970 mono_error_init (error);
6971 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6972 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6977 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6980 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6982 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6983 basename = g_path_get_basename (image->name);
6984 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6985 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6989 if (image->assembly->image == image) {
6990 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6994 if (image->assembly->image->modules) {
6995 for (i = 0; i < image->assembly->image->module_count; i++) {
6996 if (image->assembly->image->modules [i] == image)
6997 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6999 g_assert (res->token);
7003 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7006 MonoReflectionModule*
7007 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7010 MonoReflectionModule *result;
7011 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7012 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7016 MonoReflectionModule*
7017 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7019 MonoReflectionModule *res;
7020 MonoTableInfo *table;
7021 guint32 cols [MONO_FILE_SIZE];
7023 guint32 i, name_idx;
7026 mono_error_init (error);
7028 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7032 table = &image->tables [MONO_TABLE_FILE];
7033 g_assert (table_index < table->rows);
7034 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7037 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7040 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7041 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7043 /* Check whenever the row has a corresponding row in the moduleref table */
7044 table = &image->tables [MONO_TABLE_MODULEREF];
7045 for (i = 0; i < table->rows; ++i) {
7046 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7047 val = mono_metadata_string_heap (image, name_idx);
7048 if (strcmp (val, name) == 0)
7049 res->image = image->modules [i];
7052 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7053 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7054 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7055 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7056 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7062 verify_safe_for_managed_space (MonoType *type)
7064 switch (type->type) {
7066 case MONO_TYPE_ARRAY:
7067 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7069 return verify_safe_for_managed_space (type->data.type);
7070 case MONO_TYPE_SZARRAY:
7071 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7072 case MONO_TYPE_GENERICINST: {
7073 MonoGenericInst *inst = type->data.generic_class->inst;
7077 for (i = 0; i < inst->type_argc; ++i)
7078 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7084 case MONO_TYPE_MVAR:
7092 mono_type_normalize (MonoType *type)
7095 MonoGenericClass *gclass;
7096 MonoGenericInst *ginst;
7098 MonoGenericContainer *gcontainer;
7099 MonoType **argv = NULL;
7100 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7102 if (type->type != MONO_TYPE_GENERICINST)
7105 gclass = type->data.generic_class;
7106 ginst = gclass->context.class_inst;
7107 if (!ginst->is_open)
7110 gtd = gclass->container_class;
7111 gcontainer = gtd->generic_container;
7112 argv = g_newa (MonoType*, ginst->type_argc);
7114 for (i = 0; i < ginst->type_argc; ++i) {
7115 MonoType *t = ginst->type_argv [i], *norm;
7116 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7117 is_denorm_gtd = FALSE;
7118 norm = mono_type_normalize (t);
7121 requires_rebind = TRUE;
7125 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7127 if (requires_rebind) {
7128 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7129 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7135 * mono_type_get_object:
7136 * @domain: an app domain
7139 * Return an System.MonoType object representing the type @type.
7142 mono_type_get_object (MonoDomain *domain, MonoType *type)
7145 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7146 mono_error_raise_exception (&error);
7152 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7154 MonoType *norm_type;
7155 MonoReflectionType *res;
7158 mono_error_init (error);
7160 klass = mono_class_from_mono_type (type);
7162 /*we must avoid using @type as it might have come
7163 * from a mono_metadata_type_dup and the caller
7164 * expects that is can be freed.
7165 * Using the right type from
7167 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7169 /* void is very common */
7170 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7171 return (MonoReflectionType*)domain->typeof_void;
7174 * If the vtable of the given class was already created, we can use
7175 * the MonoType from there and avoid all locking and hash table lookups.
7177 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7178 * that the resulting object is different.
7180 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7181 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7182 if (vtable && vtable->type)
7183 return (MonoReflectionType *)vtable->type;
7186 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7187 mono_domain_lock (domain);
7188 if (!domain->type_hash)
7189 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7190 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7191 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7192 mono_domain_unlock (domain);
7193 mono_loader_unlock ();
7197 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7198 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7199 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7200 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7201 * artifact of how generics are encoded and should be transparent to managed code so we
7202 * need to weed out this diference when retrieving managed System.Type objects.
7204 norm_type = mono_type_normalize (type);
7205 if (norm_type != type) {
7206 res = mono_type_get_object_checked (domain, norm_type, error);
7207 if (!mono_error_ok (error))
7209 mono_g_hash_table_insert (domain->type_hash, type, res);
7210 mono_domain_unlock (domain);
7211 mono_loader_unlock ();
7215 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7216 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7219 if (!verify_safe_for_managed_space (type)) {
7220 mono_domain_unlock (domain);
7221 mono_loader_unlock ();
7222 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7226 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7227 gboolean is_type_done = TRUE;
7228 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7229 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7230 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7232 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7233 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7235 if (gparam->owner && gparam->owner->is_method) {
7236 MonoMethod *method = gparam->owner->owner.method;
7237 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7238 is_type_done = FALSE;
7239 } else if (gparam->owner && !gparam->owner->is_method) {
7240 MonoClass *klass = gparam->owner->owner.klass;
7241 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7242 is_type_done = FALSE;
7246 /* g_assert_not_reached (); */
7247 /* should this be considered an error condition? */
7248 if (is_type_done && !type->byref) {
7249 mono_domain_unlock (domain);
7250 mono_loader_unlock ();
7251 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7254 /* This is stored in vtables/JITted code so it has to be pinned */
7255 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7256 if (!mono_error_ok (error))
7260 mono_g_hash_table_insert (domain->type_hash, type, res);
7262 if (type->type == MONO_TYPE_VOID)
7263 domain->typeof_void = (MonoObject*)res;
7265 mono_domain_unlock (domain);
7266 mono_loader_unlock ();
7271 * mono_method_get_object:
7272 * @domain: an app domain
7274 * @refclass: the reflected type (can be NULL)
7276 * Return an System.Reflection.MonoMethod object representing the method @method.
7278 MonoReflectionMethod*
7279 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7282 MonoReflectionMethod *ret = NULL;
7283 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7284 mono_error_raise_exception (&error);
7289 * mono_method_get_object_checked:
7290 * @domain: an app domain
7292 * @refclass: the reflected type (can be NULL)
7293 * @error: set on error.
7295 * Return an System.Reflection.MonoMethod object representing the method @method.
7296 * Returns NULL and sets @error on error.
7298 MonoReflectionMethod*
7299 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7302 * We use the same C representation for methods and constructors, but the type
7303 * name in C# is different.
7305 MonoReflectionType *rt;
7307 MonoReflectionMethod *ret;
7309 mono_error_init (error);
7311 if (method->is_inflated) {
7312 MonoReflectionGenericMethod *gret;
7315 refclass = method->klass;
7316 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7317 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7318 klass = mono_class_get_mono_generic_cmethod_class ();
7320 klass = mono_class_get_mono_generic_method_class ();
7322 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7323 if (!mono_error_ok (error))
7325 gret->method.method = method;
7327 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7329 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7330 if (!mono_error_ok (error))
7333 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7335 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7339 refclass = method->klass;
7341 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7342 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7343 klass = mono_class_get_mono_cmethod_class ();
7346 klass = mono_class_get_mono_method_class ();
7348 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7349 if (!mono_error_ok (error))
7351 ret->method = method;
7353 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7354 if (!mono_error_ok (error))
7357 MONO_OBJECT_SETREF (ret, reftype, rt);
7359 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7362 g_assert (!mono_error_ok (error));
7367 * mono_method_clear_object:
7369 * Clear the cached reflection objects for the dynamic method METHOD.
7372 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7375 g_assert (method_is_dynamic (method));
7377 klass = method->klass;
7379 clear_cached_object (domain, method, klass);
7380 klass = klass->parent;
7382 /* Added by mono_param_get_objects () */
7383 clear_cached_object (domain, &(method->signature), NULL);
7384 klass = method->klass;
7386 clear_cached_object (domain, &(method->signature), klass);
7387 klass = klass->parent;
7392 * mono_field_get_object:
7393 * @domain: an app domain
7397 * Return an System.Reflection.MonoField object representing the field @field
7400 MonoReflectionField*
7401 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7404 MonoReflectionField *result;
7405 result = mono_field_get_object_checked (domain, klass, field, &error);
7406 mono_error_raise_exception (&error);
7411 * mono_field_get_object_checked:
7412 * @domain: an app domain
7415 * @error: set on error
7417 * Return an System.Reflection.MonoField object representing the field @field
7418 * in class @klass. On error, returns NULL and sets @error.
7420 MonoReflectionField*
7421 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7423 MonoReflectionType *rt;
7424 MonoReflectionField *res;
7426 mono_error_init (error);
7428 CHECK_OBJECT (MonoReflectionField *, field, klass);
7429 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7434 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7436 if (is_field_on_inst (field)) {
7437 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7439 rt = mono_type_get_object_checked (domain, field->type, error);
7440 if (!mono_error_ok (error))
7443 MONO_OBJECT_SETREF (res, type, rt);
7446 rt = mono_type_get_object_checked (domain, field->type, error);
7447 if (!mono_error_ok (error))
7450 MONO_OBJECT_SETREF (res, type, rt);
7452 res->attrs = mono_field_get_flags (field);
7454 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7458 * mono_property_get_object:
7459 * @domain: an app domain
7461 * @property: a property
7463 * Return an System.Reflection.MonoProperty object representing the property @property
7466 MonoReflectionProperty*
7467 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7470 MonoReflectionProperty *result;
7471 result = mono_property_get_object_checked (domain, klass, property, &error);
7472 mono_error_raise_exception (&error);
7477 * mono_property_get_object:
7478 * @domain: an app domain
7480 * @property: a property
7481 * @error: set on error
7483 * Return an System.Reflection.MonoProperty object representing the property @property
7484 * in class @klass. On error returns NULL and sets @error.
7486 MonoReflectionProperty*
7487 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7489 MonoReflectionProperty *res;
7491 mono_error_init (error);
7493 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7494 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7498 res->property = property;
7499 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7503 * mono_event_get_object:
7504 * @domain: an app domain
7508 * Return an System.Reflection.MonoEvent object representing the event @event
7511 MonoReflectionEvent*
7512 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7515 MonoReflectionEvent *result;
7516 result = mono_event_get_object_checked (domain, klass, event, &error);
7517 mono_error_raise_exception (&error);
7522 * mono_event_get_object_checked:
7523 * @domain: an app domain
7526 * @error: set on error
7528 * Return an System.Reflection.MonoEvent object representing the event @event
7529 * in class @klass. On failure sets @error and returns NULL
7531 MonoReflectionEvent*
7532 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7534 MonoReflectionEvent *res;
7535 MonoReflectionMonoEvent *mono_event;
7537 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7538 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7541 mono_event->klass = klass;
7542 mono_event->event = event;
7543 res = (MonoReflectionEvent*)mono_event;
7544 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7548 * mono_get_reflection_missing_object:
7549 * @domain: Domain where the object lives
7551 * Returns the System.Reflection.Missing.Value singleton object
7552 * (of type System.Reflection.Missing).
7554 * Used as the value for ParameterInfo.DefaultValue when Optional
7558 mono_get_reflection_missing_object (MonoDomain *domain)
7562 static MonoClassField *missing_value_field = NULL;
7564 if (!missing_value_field) {
7565 MonoClass *missing_klass;
7566 missing_klass = mono_class_get_missing_class ();
7567 mono_class_init (missing_klass);
7568 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7569 g_assert (missing_value_field);
7571 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7572 mono_error_assert_ok (&error);
7577 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7580 *dbnull = mono_get_dbnull_object (domain);
7585 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7587 if (!*reflection_missing)
7588 *reflection_missing = mono_get_reflection_missing_object (domain);
7589 return *reflection_missing;
7593 * mono_param_get_objects:
7594 * @domain: an app domain
7597 * Return an System.Reflection.ParameterInfo array object representing the parameters
7598 * in the method @method.
7601 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7603 static MonoClass *System_Reflection_ParameterInfo;
7604 static MonoClass *System_Reflection_ParameterInfo_array;
7605 MonoArray *res = NULL;
7606 MonoReflectionMethod *member = NULL;
7607 MonoReflectionParameter *param = NULL;
7608 char **names = NULL, **blobs = NULL;
7609 guint32 *types = NULL;
7610 MonoType *type = NULL;
7611 MonoObject *dbnull = NULL;
7612 MonoObject *missing = NULL;
7613 MonoMarshalSpec **mspecs = NULL;
7614 MonoMethodSignature *sig = NULL;
7615 MonoVTable *pinfo_vtable;
7616 MonoReflectionType *rt;
7619 mono_error_init (error);
7621 if (!System_Reflection_ParameterInfo_array) {
7624 klass = mono_class_get_mono_parameter_info_class ();
7626 mono_memory_barrier ();
7627 System_Reflection_ParameterInfo = klass;
7630 klass = mono_array_class_get (klass, 1);
7631 mono_memory_barrier ();
7632 System_Reflection_ParameterInfo_array = klass;
7635 sig = mono_method_signature_checked (method, error);
7636 if (!mono_error_ok (error))
7639 if (!sig->param_count) {
7640 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7647 /* Note: the cache is based on the address of the signature into the method
7648 * since we already cache MethodInfos with the method as keys.
7650 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7652 member = mono_method_get_object_checked (domain, method, refclass, error);
7655 names = g_new (char *, sig->param_count);
7656 mono_method_get_param_names (method, (const char **) names);
7658 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7659 mono_method_get_marshal_info (method, mspecs);
7661 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7665 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7666 for (i = 0; i < sig->param_count; ++i) {
7667 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7671 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7675 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7677 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7679 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7681 param->PositionImpl = i;
7682 param->AttrsImpl = sig->params [i]->attrs;
7684 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7685 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7686 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7688 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7692 blobs = g_new0 (char *, sig->param_count);
7693 types = g_new0 (guint32, sig->param_count);
7694 get_default_param_value_blobs (method, blobs, types);
7697 /* Build MonoType for the type from the Constant Table */
7699 type = g_new0 (MonoType, 1);
7700 type->type = (MonoTypeEnum)types [i];
7701 type->data.klass = NULL;
7702 if (types [i] == MONO_TYPE_CLASS)
7703 type->data.klass = mono_defaults.object_class;
7704 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7705 /* For enums, types [i] contains the base type */
7707 type->type = MONO_TYPE_VALUETYPE;
7708 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7710 type->data.klass = mono_class_from_mono_type (type);
7712 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7715 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7717 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7718 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7719 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7720 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7722 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7727 if (mspecs [i + 1]) {
7728 MonoReflectionMarshalAsAttribute* mobj;
7729 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7732 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7735 mono_array_setref (res, i, param);
7745 for (i = sig->param_count; i >= 0; i--) {
7747 mono_metadata_free_marshal_spec (mspecs [i]);
7755 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7759 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7762 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7763 mono_error_assert_ok (&error);
7768 * mono_method_body_get_object:
7769 * @domain: an app domain
7772 * Return an System.Reflection.MethodBody object representing the method @method.
7774 MonoReflectionMethodBody*
7775 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7778 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7779 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7784 * mono_method_body_get_object_checked:
7785 * @domain: an app domain
7787 * @error: set on error
7789 * Return an System.Reflection.MethodBody object representing the
7790 * method @method. On failure, returns NULL and sets @error.
7792 MonoReflectionMethodBody*
7793 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7795 MonoReflectionMethodBody *ret;
7796 MonoMethodHeader *header;
7798 MonoReflectionType *rt;
7799 guint32 method_rva, local_var_sig_token;
7801 unsigned char format, flags;
7804 mono_error_init (error);
7806 /* for compatibility with .net */
7807 if (method_is_dynamic (method)) {
7808 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7812 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7814 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7815 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7816 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7817 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7818 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7821 image = method->klass->image;
7822 header = mono_method_get_header_checked (method, error);
7823 return_val_if_nok (error, NULL);
7825 if (!image_is_dynamic (image)) {
7826 /* Obtain local vars signature token */
7827 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7828 ptr = mono_image_rva_map (image, method_rva);
7829 flags = *(const unsigned char *) ptr;
7830 format = flags & METHOD_HEADER_FORMAT_MASK;
7832 case METHOD_HEADER_TINY_FORMAT:
7833 local_var_sig_token = 0;
7835 case METHOD_HEADER_FAT_FORMAT:
7839 local_var_sig_token = read32 (ptr);
7842 g_assert_not_reached ();
7845 local_var_sig_token = 0; //FIXME
7847 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7851 ret->init_locals = header->init_locals;
7852 ret->max_stack = header->max_stack;
7853 ret->local_var_sig_token = local_var_sig_token;
7854 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7855 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7858 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7859 for (i = 0; i < header->num_locals; ++i) {
7860 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7864 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7868 MONO_OBJECT_SETREF (info, local_type, rt);
7870 info->is_pinned = header->locals [i]->pinned;
7871 info->local_index = i;
7872 mono_array_setref (ret->locals, i, info);
7876 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7877 for (i = 0; i < header->num_clauses; ++i) {
7878 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7881 MonoExceptionClause *clause = &header->clauses [i];
7883 info->flags = clause->flags;
7884 info->try_offset = clause->try_offset;
7885 info->try_length = clause->try_len;
7886 info->handler_offset = clause->handler_offset;
7887 info->handler_length = clause->handler_len;
7888 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7889 info->filter_offset = clause->data.filter_offset;
7890 else if (clause->data.catch_class) {
7891 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7895 MONO_OBJECT_SETREF (info, catch_type, rt);
7898 mono_array_setref (ret->clauses, i, info);
7901 mono_metadata_free_mh (header);
7902 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7906 mono_metadata_free_mh (header);
7911 * mono_get_dbnull_object:
7912 * @domain: Domain where the object lives
7914 * Returns the System.DBNull.Value singleton object
7916 * Used as the value for ParameterInfo.DefaultValue
7919 mono_get_dbnull_object (MonoDomain *domain)
7923 static MonoClassField *dbnull_value_field = NULL;
7925 if (!dbnull_value_field) {
7926 MonoClass *dbnull_klass;
7927 dbnull_klass = mono_class_get_dbnull_class ();
7928 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7929 g_assert (dbnull_value_field);
7931 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7932 mono_error_assert_ok (&error);
7937 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7939 guint32 param_index, i, lastp, crow = 0;
7940 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7943 MonoClass *klass = method->klass;
7944 MonoImage *image = klass->image;
7945 MonoMethodSignature *methodsig = mono_method_signature (method);
7947 MonoTableInfo *constt;
7948 MonoTableInfo *methodt;
7949 MonoTableInfo *paramt;
7951 if (!methodsig->param_count)
7954 mono_class_init (klass);
7956 if (image_is_dynamic (klass->image)) {
7957 MonoReflectionMethodAux *aux;
7958 if (method->is_inflated)
7959 method = ((MonoMethodInflated*)method)->declaring;
7960 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7961 if (aux && aux->param_defaults) {
7962 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7963 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7968 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7969 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7970 constt = &image->tables [MONO_TABLE_CONSTANT];
7972 idx = mono_method_get_index (method) - 1;
7973 g_assert (idx != -1);
7975 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7976 if (idx + 1 < methodt->rows)
7977 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7979 lastp = paramt->rows + 1;
7981 for (i = param_index; i < lastp; ++i) {
7984 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7985 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7987 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7990 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7995 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7996 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7997 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8004 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8009 MonoType *basetype = type;
8011 mono_error_init (error);
8016 klass = mono_class_from_mono_type (type);
8017 if (klass->valuetype) {
8018 object = mono_object_new_checked (domain, klass, error);
8019 return_val_if_nok (error, NULL);
8020 retval = ((gchar *) object + sizeof (MonoObject));
8021 if (klass->enumtype)
8022 basetype = mono_class_enum_basetype (klass);
8027 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
8034 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8037 gboolean quoted = FALSE;
8039 memset (assembly, 0, sizeof (MonoAssemblyName));
8040 assembly->culture = "";
8041 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8048 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8059 /* Remove trailing whitespace */
8061 while (*s && g_ascii_isspace (*s))
8064 while (g_ascii_isspace (*p))
8067 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8069 assembly->major = strtoul (p, &s, 10);
8070 if (s == p || *s != '.')
8073 assembly->minor = strtoul (p, &s, 10);
8074 if (s == p || *s != '.')
8077 assembly->build = strtoul (p, &s, 10);
8078 if (s == p || *s != '.')
8081 assembly->revision = strtoul (p, &s, 10);
8085 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8087 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8088 assembly->culture = "";
8091 assembly->culture = p;
8092 while (*p && *p != ',') {
8096 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8098 if (strncmp (p, "null", 4) == 0) {
8103 while (*p && *p != ',') {
8106 len = (p - start + 1);
8107 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8108 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8109 g_strlcpy ((char*)assembly->public_key_token, start, len);
8112 while (*p && *p != ',')
8116 while (g_ascii_isspace (*p) || *p == ',') {
8130 * mono_reflection_parse_type:
8133 * Parse a type name as accepted by the GetType () method and output the info
8134 * extracted in the info structure.
8135 * the name param will be mangled, so, make a copy before passing it to this function.
8136 * The fields in info will be valid until the memory pointed to by name is valid.
8138 * See also mono_type_get_name () below.
8140 * Returns: 0 on parse error.
8143 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8144 MonoTypeNameParse *info)
8146 char *start, *p, *w, *last_point, *startn;
8147 int in_modifiers = 0;
8148 int isbyref = 0, rank = 0, isptr = 0;
8150 start = p = w = name;
8152 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8153 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8154 info->name = info->name_space = NULL;
8155 info->nested = NULL;
8156 info->modifiers = NULL;
8157 info->type_arguments = NULL;
8159 /* last_point separates the namespace from the name */
8162 while (*p == ' ') p++, start++, w++, name++;
8167 *p = 0; /* NULL terminate the name */
8169 info->nested = g_list_append (info->nested, startn);
8170 /* we have parsed the nesting namespace + name */
8174 info->name_space = start;
8176 info->name = last_point + 1;
8178 info->name_space = (char *)"";
8206 info->name_space = start;
8208 info->name = last_point + 1;
8210 info->name_space = (char *)"";
8217 if (isbyref) /* only one level allowed by the spec */
8221 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8225 if (isbyref) /* pointer to ref not okay */
8227 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8232 if (isbyref) /* array of ref and generic ref are not okay */
8234 //Decide if it's an array of a generic argument list
8239 if (*p == ',' || *p == '*' || *p == ']') { //array
8247 else if (*p == '*') /* '*' means unknown lower bound */
8248 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8255 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8257 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8260 info->type_arguments = g_ptr_array_new ();
8262 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8263 gboolean fqname = FALSE;
8265 g_ptr_array_add (info->type_arguments, subinfo);
8267 while (*p == ' ') p++;
8273 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8276 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8277 if (fqname && (*p != ']')) {
8285 while (*p && (*p != ']'))
8293 if (g_ascii_isspace (*aname)) {
8300 !assembly_name_to_aname (&subinfo->assembly, aname))
8302 } else if (fqname && (*p == ']')) {
8324 if (g_ascii_isspace (*p)) {
8331 return 0; /* missing assembly name */
8332 if (!assembly_name_to_aname (&info->assembly, p))
8338 if (info->assembly.name)
8341 // *w = 0; /* terminate class name */
8343 if (!info->name || !*info->name)
8347 /* add other consistency checks */
8353 * mono_identifier_unescape_type_name_chars:
8354 * @identifier: the display name of a mono type
8357 * The name in internal form, that is without escaping backslashes.
8359 * The string is modified in place!
8362 mono_identifier_unescape_type_name_chars(char* identifier)
8367 for (w = r = identifier; *r != 0; r++)
8385 mono_identifier_unescape_info (MonoTypeNameParse* info);
8388 unescape_each_type_argument(void* data, void* user_data)
8390 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8391 mono_identifier_unescape_info (info);
8395 unescape_each_nested_name (void* data, void* user_data)
8397 char* nested_name = (char*) data;
8398 mono_identifier_unescape_type_name_chars(nested_name);
8402 * mono_identifier_unescape_info:
8404 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8408 * Destructively updates the info by unescaping the identifiers that
8409 * comprise the type namespace, name, nested types (if any) and
8410 * generic type arguments (if any).
8412 * The resulting info has the names in internal form.
8416 mono_identifier_unescape_info (MonoTypeNameParse *info)
8420 mono_identifier_unescape_type_name_chars(info->name_space);
8421 mono_identifier_unescape_type_name_chars(info->name);
8422 // but don't escape info->assembly
8423 if (info->type_arguments)
8424 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8426 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8430 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8432 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8434 mono_identifier_unescape_info (info);
8440 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8442 gboolean type_resolve = FALSE;
8444 MonoImage *rootimage = image;
8446 mono_error_init (error);
8448 if (info->assembly.name) {
8449 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8450 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8452 * This could happen in the AOT compiler case when the search hook is not
8455 assembly = image->assembly;
8457 /* then we must load the assembly ourselve - see #60439 */
8458 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8462 image = assembly->image;
8463 } else if (!image) {
8464 image = mono_defaults.corlib;
8467 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8468 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8469 mono_error_cleanup (error);
8470 image = mono_defaults.corlib;
8471 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8478 * mono_reflection_get_type_internal:
8480 * Returns: may return NULL on success, sets error on failure.
8483 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8488 gboolean bounded = FALSE;
8490 mono_error_init (error);
8492 image = mono_defaults.corlib;
8495 rootimage = mono_defaults.corlib;
8498 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8500 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8505 for (mod = info->nested; mod; mod = mod->next) {
8506 gpointer iter = NULL;
8510 mono_class_init (parent);
8512 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8514 char *nested_name, *nested_nspace;
8515 gboolean match = TRUE;
8517 lastp = strrchr ((const char *)mod->data, '.');
8519 /* Nested classes can have namespaces */
8522 nested_name = g_strdup (lastp + 1);
8523 nspace_len = lastp - (char*)mod->data;
8524 nested_nspace = (char *)g_malloc (nspace_len + 1);
8525 memcpy (nested_nspace, mod->data, nspace_len);
8526 nested_nspace [nspace_len] = '\0';
8529 nested_name = (char *)mod->data;
8530 nested_nspace = NULL;
8533 if (nested_nspace) {
8535 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8538 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8544 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8547 if (strcmp (klass->name, nested_name) != 0)
8552 g_free (nested_name);
8553 g_free (nested_nspace);
8565 if (info->type_arguments) {
8566 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8567 MonoReflectionType *the_type;
8571 for (i = 0; i < info->type_arguments->len; i++) {
8572 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8574 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8575 if (!type_args [i]) {
8581 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8585 instance = mono_reflection_bind_generic_parameters (
8586 the_type, info->type_arguments->len, type_args, error);
8592 klass = mono_class_from_mono_type (instance);
8595 for (mod = info->modifiers; mod; mod = mod->next) {
8596 modval = GPOINTER_TO_UINT (mod->data);
8597 if (!modval) { /* byref: must be last modifier */
8598 return &klass->this_arg;
8599 } else if (modval == -1) {
8600 klass = mono_ptr_class_get (&klass->byval_arg);
8601 } else if (modval == -2) {
8603 } else { /* array rank */
8604 klass = mono_bounded_array_class_get (klass, modval, bounded);
8608 return &klass->byval_arg;
8612 * mono_reflection_get_type:
8613 * @image: a metadata context
8614 * @info: type description structure
8615 * @ignorecase: flag for case-insensitive string compares
8616 * @type_resolve: whenever type resolve was already tried
8618 * Build a MonoType from the type description in @info.
8623 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8625 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8626 mono_error_cleanup (&error);
8631 * mono_reflection_get_type_checked:
8632 * @image: a metadata context
8633 * @info: type description structure
8634 * @ignorecase: flag for case-insensitive string compares
8635 * @type_resolve: whenever type resolve was already tried
8636 * @error: set on error.
8638 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8642 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8643 mono_error_init (error);
8644 return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8649 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8651 MonoReflectionAssemblyBuilder *abuilder;
8655 mono_error_init (error);
8656 g_assert (assembly_is_dynamic (assembly));
8657 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8661 /* Enumerate all modules */
8664 if (abuilder->modules) {
8665 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8666 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8667 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8670 if (!mono_error_ok (error))
8675 if (!type && abuilder->loaded_modules) {
8676 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8677 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8678 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8681 if (!mono_error_ok (error))
8690 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8693 MonoReflectionAssembly *assembly;
8697 mono_error_init (error);
8699 if (image && image_is_dynamic (image))
8700 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8702 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8704 return_val_if_nok (error, NULL);
8708 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8715 *type_resolve = TRUE;
8718 /* Reconstruct the type name */
8719 fullName = g_string_new ("");
8720 if (info->name_space && (info->name_space [0] != '\0'))
8721 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8723 g_string_printf (fullName, "%s", info->name);
8724 for (mod = info->nested; mod; mod = mod->next)
8725 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8727 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8728 if (!is_ok (error)) {
8729 g_string_free (fullName, TRUE);
8734 if (assembly_is_dynamic (assembly->assembly))
8735 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8736 info, ignorecase, error);
8738 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8739 info, ignorecase, error);
8741 g_string_free (fullName, TRUE);
8742 return_val_if_nok (error, NULL);
8747 mono_reflection_free_type_info (MonoTypeNameParse *info)
8749 g_list_free (info->modifiers);
8750 g_list_free (info->nested);
8752 if (info->type_arguments) {
8755 for (i = 0; i < info->type_arguments->len; i++) {
8756 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8758 mono_reflection_free_type_info (subinfo);
8759 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8763 g_ptr_array_free (info->type_arguments, TRUE);
8768 * mono_reflection_type_from_name:
8770 * @image: a metadata context (can be NULL).
8772 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8773 * it defaults to get the type from @image or, if @image is NULL or loading
8774 * from it fails, uses corlib.
8778 mono_reflection_type_from_name (char *name, MonoImage *image)
8781 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8782 mono_error_cleanup (&error);
8787 * mono_reflection_type_from_name_checked:
8789 * @image: a metadata context (can be NULL).
8790 * @error: set on errror.
8792 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8793 * it defaults to get the type from @image or, if @image is NULL or loading
8794 * from it fails, uses corlib. On failure returns NULL and sets @error.
8798 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8800 MonoType *type = NULL;
8801 MonoTypeNameParse info;
8804 mono_error_init (error);
8805 /* Make a copy since parse_type modifies its argument */
8806 tmp = g_strdup (name);
8808 /*g_print ("requested type %s\n", str);*/
8809 if (mono_reflection_parse_type (tmp, &info)) {
8810 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8811 if (!is_ok (error)) {
8813 mono_reflection_free_type_info (&info);
8819 mono_reflection_free_type_info (&info);
8824 * mono_reflection_get_token:
8826 * Return the metadata token of OBJ which should be an object
8827 * representing a metadata element.
8830 mono_reflection_get_token (MonoObject *obj)
8833 guint32 result = mono_reflection_get_token_checked (obj, &error);
8834 mono_error_assert_ok (&error);
8839 * mono_reflection_get_token_checked:
8841 * @error: set on error
8843 * Return the metadata token of @obj which should be an object
8844 * representing a metadata element. On failure sets @error.
8847 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8852 mono_error_init (error);
8854 klass = obj->vtable->klass;
8856 if (strcmp (klass->name, "MethodBuilder") == 0) {
8857 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8859 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8860 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8861 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8863 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8864 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8865 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8867 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8868 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8869 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8870 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8871 } else if (strcmp (klass->name, "MonoType") == 0) {
8872 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8873 return_val_if_nok (error, 0);
8874 MonoClass *mc = mono_class_from_mono_type (type);
8875 if (!mono_class_init (mc)) {
8876 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8880 token = mc->type_token;
8881 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8882 strcmp (klass->name, "MonoMethod") == 0 ||
8883 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8884 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8885 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8886 if (m->method->is_inflated) {
8887 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8888 return inflated->declaring->token;
8890 token = m->method->token;
8892 } else if (strcmp (klass->name, "MonoField") == 0) {
8893 MonoReflectionField *f = (MonoReflectionField*)obj;
8895 if (is_field_on_inst (f->field)) {
8896 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8898 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8899 int field_index = f->field - dgclass->fields;
8902 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8903 obj = dgclass->field_objects [field_index];
8904 return mono_reflection_get_token_checked (obj, error);
8907 token = mono_class_get_field_token (f->field);
8908 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8909 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8911 token = mono_class_get_property_token (p->property);
8912 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8913 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8915 token = mono_class_get_event_token (p->event);
8916 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8917 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8918 MonoClass *member_class = mono_object_class (p->MemberImpl);
8919 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8921 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8922 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8923 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8926 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8927 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8929 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8930 klass->name_space, klass->name);
8938 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8942 int slen = mono_metadata_decode_value (p, &p);
8944 mono_error_init (error);
8946 n = (char *)g_memdup (p, slen + 1);
8948 t = mono_reflection_type_from_name_checked (n, image, error);
8950 char *msg = g_strdup (mono_error_get_message (error));
8951 mono_error_cleanup (error);
8952 /* We don't free n, it's consumed by mono_error */
8953 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8960 return mono_class_from_mono_type (t);
8964 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8966 int slen, type = t->type;
8967 MonoClass *tklass = t->data.klass;
8969 mono_error_init (error);
8975 case MONO_TYPE_BOOLEAN: {
8976 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8981 case MONO_TYPE_CHAR:
8983 case MONO_TYPE_I2: {
8984 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8989 #if SIZEOF_VOID_P == 4
8995 case MONO_TYPE_I4: {
8996 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9001 #if SIZEOF_VOID_P == 8
9002 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9006 case MONO_TYPE_I8: {
9007 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9012 case MONO_TYPE_R8: {
9013 double *val = (double *)g_malloc (sizeof (double));
9018 case MONO_TYPE_VALUETYPE:
9019 if (t->data.klass->enumtype) {
9020 type = mono_class_enum_basetype (t->data.klass)->type;
9023 MonoClass *k = t->data.klass;
9025 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9026 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9032 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9035 case MONO_TYPE_STRING:
9036 if (*p == (char)0xFF) {
9040 slen = mono_metadata_decode_value (p, &p);
9042 return mono_string_new_len (mono_domain_get (), p, slen);
9043 case MONO_TYPE_CLASS: {
9044 MonoReflectionType *rt;
9047 if (*p == (char)0xFF) {
9052 slen = mono_metadata_decode_value (p, &p);
9053 n = (char *)g_memdup (p, slen + 1);
9055 t = mono_reflection_type_from_name_checked (n, image, error);
9057 char *msg = g_strdup (mono_error_get_message (error));
9058 mono_error_cleanup (error);
9059 /* We don't free n, it's consumed by mono_error */
9060 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9067 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9068 if (!mono_error_ok (error))
9073 case MONO_TYPE_OBJECT: {
9076 MonoClass *subc = NULL;
9081 } else if (subt == 0x0E) {
9082 type = MONO_TYPE_STRING;
9084 } else if (subt == 0x1D) {
9085 MonoType simple_type = {{0}};
9089 type = MONO_TYPE_SZARRAY;
9090 if (etype == 0x50) {
9091 tklass = mono_defaults.systemtype_class;
9092 } else if (etype == 0x55) {
9093 tklass = load_cattr_enum_type (image, p, &p, error);
9094 if (!mono_error_ok (error))
9098 /* See Partition II, Appendix B3 */
9099 etype = MONO_TYPE_OBJECT;
9100 simple_type.type = (MonoTypeEnum)etype;
9101 tklass = mono_class_from_mono_type (&simple_type);
9104 } else if (subt == 0x55) {
9107 slen = mono_metadata_decode_value (p, &p);
9108 n = (char *)g_memdup (p, slen + 1);
9110 t = mono_reflection_type_from_name_checked (n, image, error);
9112 char *msg = g_strdup (mono_error_get_message (error));
9113 mono_error_cleanup (error);
9114 /* We don't free n, it's consumed by mono_error */
9115 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9121 subc = mono_class_from_mono_type (t);
9122 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9123 MonoType simple_type = {{0}};
9124 simple_type.type = (MonoTypeEnum)subt;
9125 subc = mono_class_from_mono_type (&simple_type);
9127 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9129 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9131 if (mono_error_ok (error)) {
9132 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9133 g_assert (!subc->has_references);
9134 if (mono_error_ok (error))
9135 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9141 case MONO_TYPE_SZARRAY: {
9143 guint32 i, alen, basetype;
9146 if (alen == 0xffffffff) {
9150 arr = mono_array_new (mono_domain_get(), tklass, alen);
9151 basetype = tklass->byval_arg.type;
9152 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9153 basetype = mono_class_enum_basetype (tklass)->type;
9158 case MONO_TYPE_BOOLEAN:
9159 for (i = 0; i < alen; i++) {
9160 MonoBoolean val = *p++;
9161 mono_array_set (arr, MonoBoolean, i, val);
9164 case MONO_TYPE_CHAR:
9167 for (i = 0; i < alen; i++) {
9168 guint16 val = read16 (p);
9169 mono_array_set (arr, guint16, i, val);
9176 for (i = 0; i < alen; i++) {
9177 guint32 val = read32 (p);
9178 mono_array_set (arr, guint32, i, val);
9183 for (i = 0; i < alen; i++) {
9186 mono_array_set (arr, double, i, val);
9192 for (i = 0; i < alen; i++) {
9193 guint64 val = read64 (p);
9194 mono_array_set (arr, guint64, i, val);
9198 case MONO_TYPE_CLASS:
9199 case MONO_TYPE_OBJECT:
9200 case MONO_TYPE_STRING:
9201 case MONO_TYPE_SZARRAY:
9202 for (i = 0; i < alen; i++) {
9203 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9204 if (!mono_error_ok (error))
9206 mono_array_setref (arr, i, item);
9210 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9216 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9222 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9224 mono_error_init (error);
9226 gboolean is_ref = type_is_reference (t);
9228 void *val = load_cattr_value (image, t, p, end, error);
9229 if (!is_ok (error)) {
9236 return (MonoObject*)val;
9238 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9244 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9246 static MonoMethod *ctor;
9248 void *params [2], *unboxed;
9250 mono_error_init (error);
9253 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9255 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9256 return_val_if_nok (error, NULL);
9259 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9260 return_val_if_nok (error, NULL);
9261 unboxed = mono_object_unbox (retval);
9263 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9264 return_val_if_nok (error, NULL);
9270 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9272 static MonoMethod *ctor;
9274 void *unboxed, *params [2];
9276 mono_error_init (error);
9279 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9282 params [1] = typedarg;
9283 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9284 return_val_if_nok (error, NULL);
9286 unboxed = mono_object_unbox (retval);
9288 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9289 return_val_if_nok (error, NULL);
9295 type_is_reference (MonoType *type)
9297 switch (type->type) {
9298 case MONO_TYPE_BOOLEAN:
9299 case MONO_TYPE_CHAR:
9312 case MONO_TYPE_VALUETYPE:
9320 free_param_data (MonoMethodSignature *sig, void **params) {
9322 for (i = 0; i < sig->param_count; ++i) {
9323 if (!type_is_reference (sig->params [i]))
9324 g_free (params [i]);
9329 * Find the field index in the metadata FieldDef table.
9332 find_field_index (MonoClass *klass, MonoClassField *field) {
9335 for (i = 0; i < klass->field.count; ++i) {
9336 if (field == &klass->fields [i])
9337 return klass->field.first + 1 + i;
9343 * Find the property index in the metadata Property table.
9346 find_property_index (MonoClass *klass, MonoProperty *property) {
9349 for (i = 0; i < klass->ext->property.count; ++i) {
9350 if (property == &klass->ext->properties [i])
9351 return klass->ext->property.first + 1 + i;
9357 * Find the event index in the metadata Event table.
9360 find_event_index (MonoClass *klass, MonoEvent *event) {
9363 for (i = 0; i < klass->ext->event.count; ++i) {
9364 if (event == &klass->ext->events [i])
9365 return klass->ext->event.first + 1 + i;
9371 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9373 const char *p = (const char*)data;
9375 guint32 i, j, num_named;
9377 void *params_buf [32];
9378 void **params = NULL;
9379 MonoMethodSignature *sig;
9380 MonoObject *exc = NULL;
9382 mono_error_init (error);
9384 mono_class_init (method->klass);
9386 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9387 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9392 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9393 if (!mono_error_ok (error)) return NULL;
9395 mono_runtime_invoke_checked (method, attr, NULL, error);
9396 if (!mono_error_ok (error))
9402 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9405 /*g_print ("got attr %s\n", method->klass->name);*/
9407 sig = mono_method_signature (method);
9408 if (sig->param_count < 32) {
9409 params = params_buf;
9410 memset (params, 0, sizeof (void*) * sig->param_count);
9412 /* Allocate using GC so it gets GC tracking */
9413 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9418 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9419 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9420 if (!mono_error_ok (error))
9425 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9426 if (!mono_error_ok (error)) goto fail;
9428 mono_runtime_try_invoke (method, attr, params, &exc, error);
9429 if (!mono_error_ok (error))
9434 num_named = read16 (named);
9436 for (j = 0; j < num_named; j++) {
9438 char *name, named_type, data_type;
9439 named_type = *named++;
9440 data_type = *named++; /* type of data */
9441 if (data_type == MONO_TYPE_SZARRAY)
9442 data_type = *named++;
9443 if (data_type == MONO_TYPE_ENUM) {
9446 type_len = mono_metadata_decode_blob_size (named, &named);
9447 type_name = (char *)g_malloc (type_len + 1);
9448 memcpy (type_name, named, type_len);
9449 type_name [type_len] = 0;
9451 /* FIXME: lookup the type and check type consistency */
9454 name_len = mono_metadata_decode_blob_size (named, &named);
9455 name = (char *)g_malloc (name_len + 1);
9456 memcpy (name, named, name_len);
9457 name [name_len] = 0;
9459 if (named_type == 0x53) {
9460 MonoClassField *field;
9463 /* how this fail is a blackbox */
9464 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9466 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9471 val = load_cattr_value (image, field->type, named, &named, error);
9472 if (!mono_error_ok (error)) {
9474 if (!type_is_reference (field->type))
9479 mono_field_set_value (attr, field, val);
9480 if (!type_is_reference (field->type))
9482 } else if (named_type == 0x54) {
9485 MonoType *prop_type;
9487 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9490 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9496 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9501 /* can we have more that 1 arg in a custom attr named property? */
9502 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9503 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9505 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9506 if (!mono_error_ok (error)) {
9508 if (!type_is_reference (prop_type))
9509 g_free (pparams [0]);
9514 mono_property_set_value (prop, attr, pparams, NULL);
9515 if (!type_is_reference (prop_type))
9516 g_free (pparams [0]);
9521 free_param_data (method->signature, params);
9522 if (params != params_buf)
9523 mono_gc_free_fixed (params);
9528 free_param_data (method->signature, params);
9529 if (params != params_buf)
9530 mono_gc_free_fixed (params);
9532 mono_raise_exception ((MonoException*)exc);
9537 * mono_reflection_create_custom_attr_data_args:
9539 * Create an array of typed and named arguments from the cattr blob given by DATA.
9540 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9541 * NAMED_ARG_INFO will contain information about the named arguments.
9544 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)
9546 MonoArray *typedargs, *namedargs;
9547 MonoClass *attrklass;
9549 const char *p = (const char*)data;
9551 guint32 i, j, num_named;
9552 CattrNamedArg *arginfo = NULL;
9556 *named_arg_info = NULL;
9558 mono_error_init (error);
9560 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9561 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9565 mono_class_init (method->klass);
9567 domain = mono_domain_get ();
9569 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9572 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9576 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9579 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9580 return_if_nok (error);
9581 mono_array_setref (typedargs, i, obj);
9585 num_named = read16 (named);
9586 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9588 attrklass = method->klass;
9590 arginfo = g_new0 (CattrNamedArg, num_named);
9591 *named_arg_info = arginfo;
9593 for (j = 0; j < num_named; j++) {
9595 char *name, named_type, data_type;
9596 named_type = *named++;
9597 data_type = *named++; /* type of data */
9598 if (data_type == MONO_TYPE_SZARRAY)
9599 data_type = *named++;
9600 if (data_type == MONO_TYPE_ENUM) {
9603 type_len = mono_metadata_decode_blob_size (named, &named);
9604 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9607 type_name = (char *)g_malloc (type_len + 1);
9608 memcpy (type_name, named, type_len);
9609 type_name [type_len] = 0;
9611 /* FIXME: lookup the type and check type consistency */
9614 name_len = mono_metadata_decode_blob_size (named, &named);
9615 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9617 name = (char *)g_malloc (name_len + 1);
9618 memcpy (name, named, name_len);
9619 name [name_len] = 0;
9621 if (named_type == 0x53) {
9623 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9630 arginfo [j].type = field->type;
9631 arginfo [j].field = field;
9633 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9634 if (!is_ok (error)) {
9638 mono_array_setref (namedargs, j, obj);
9640 } else if (named_type == 0x54) {
9642 MonoType *prop_type;
9643 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9645 if (!prop || !prop->set) {
9650 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9651 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9653 arginfo [j].type = prop_type;
9654 arginfo [j].prop = prop;
9656 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9657 if (!is_ok (error)) {
9661 mono_array_setref (namedargs, j, obj);
9666 *typed_args = typedargs;
9667 *named_args = namedargs;
9670 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9672 *named_arg_info = NULL;
9676 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9679 MonoArray *typedargs, *namedargs;
9682 CattrNamedArg *arginfo = NULL;
9686 mono_error_init (&error);
9694 image = assembly->assembly->image;
9695 method = ref_method->method;
9696 domain = mono_object_domain (ref_method);
9698 if (!mono_class_init (method->klass))
9699 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9701 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9702 if (!mono_error_ok (&error))
9705 if (mono_loader_get_last_error ()) {
9706 mono_error_set_from_loader_error (&error);
9710 if (!typedargs || !namedargs)
9713 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9714 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9715 MonoObject *typedarg;
9717 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9718 if (!is_ok (&error))
9720 mono_array_setref (typedargs, i, typedarg);
9723 for (i = 0; i < mono_array_length (namedargs); ++i) {
9724 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9725 MonoObject *typedarg, *namedarg, *minfo;
9727 if (arginfo [i].prop) {
9728 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9732 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9733 if (!mono_error_ok (&error))
9737 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9738 if (!is_ok (&error))
9740 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9741 if (!is_ok (&error))
9744 mono_array_setref (namedargs, i, namedarg);
9747 *ctor_args = typedargs;
9748 *named_args = namedargs;
9751 mono_error_raise_exception (&error);
9756 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9758 static MonoMethod *ctor;
9764 mono_error_init (error);
9766 g_assert (image->assembly);
9769 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9771 domain = mono_domain_get ();
9772 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9773 return_val_if_nok (error, NULL);
9774 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9775 return_val_if_nok (error, NULL);
9776 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9777 return_val_if_nok (error, NULL);
9778 params [2] = (gpointer)&cattr->data;
9779 params [3] = &cattr->data_size;
9781 mono_runtime_invoke_checked (ctor, attr, params, error);
9782 return_val_if_nok (error, NULL);
9787 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9793 mono_error_init (error);
9796 for (i = 0; i < cinfo->num_attrs; ++i) {
9797 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9801 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9803 for (i = 0; i < cinfo->num_attrs; ++i) {
9804 if (!cinfo->attrs [i].ctor) {
9805 /* The cattr type is not finished yet */
9806 /* We should include the type name but cinfo doesn't contain it */
9807 mono_error_set_type_load_name (error, NULL, NULL, "");
9810 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9811 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9812 if (!mono_error_ok (error))
9814 mono_array_setref (result, n, attr);
9822 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9825 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9826 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9832 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9838 mono_error_init (error);
9839 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9840 for (i = 0; i < cinfo->num_attrs; ++i) {
9841 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9842 return_val_if_nok (error, NULL);
9843 mono_array_setref (result, i, attr);
9849 * mono_custom_attrs_from_index:
9851 * Returns: NULL if no attributes are found or if a loading error occurs.
9854 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9857 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9858 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9862 * mono_custom_attrs_from_index_checked:
9864 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9867 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9869 guint32 mtoken, i, len;
9870 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9872 MonoCustomAttrInfo *ainfo;
9873 GList *tmp, *list = NULL;
9875 MonoCustomAttrEntry* attr;
9877 mono_error_init (error);
9879 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9881 i = mono_metadata_custom_attrs_from_index (image, idx);
9885 while (i < ca->rows) {
9886 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9888 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9891 len = g_list_length (list);
9894 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9895 ainfo->num_attrs = len;
9896 ainfo->image = image;
9897 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9898 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9899 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9900 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9901 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9902 mtoken |= MONO_TOKEN_METHOD_DEF;
9904 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9905 mtoken |= MONO_TOKEN_MEMBER_REF;
9908 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9911 attr = &ainfo->attrs [i - 1];
9912 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9914 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9920 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9921 /*FIXME raising an exception here doesn't make any sense*/
9922 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9927 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9928 attr->data_size = mono_metadata_decode_value (data, &data);
9929 attr->data = (guchar*)data;
9937 mono_custom_attrs_from_method (MonoMethod *method)
9940 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9941 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9946 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9950 mono_error_init (error);
9953 * An instantiated method has the same cattrs as the generic method definition.
9955 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9956 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9958 if (method->is_inflated)
9959 method = ((MonoMethodInflated *) method)->declaring;
9961 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9962 return lookup_custom_attr (method->klass->image, method);
9965 /* Synthetic methods */
9968 idx = mono_method_get_index (method);
9969 idx <<= MONO_CUSTOM_ATTR_BITS;
9970 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9971 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9975 mono_custom_attrs_from_class (MonoClass *klass)
9978 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9979 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9984 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9988 mono_error_init (error);
9990 if (klass->generic_class)
9991 klass = klass->generic_class->container_class;
9993 if (image_is_dynamic (klass->image))
9994 return lookup_custom_attr (klass->image, klass);
9996 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9997 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9998 idx <<= MONO_CUSTOM_ATTR_BITS;
9999 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10001 idx = mono_metadata_token_index (klass->type_token);
10002 idx <<= MONO_CUSTOM_ATTR_BITS;
10003 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10005 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10008 MonoCustomAttrInfo*
10009 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10012 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10013 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10017 MonoCustomAttrInfo*
10018 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10022 mono_error_init (error);
10024 if (image_is_dynamic (assembly->image))
10025 return lookup_custom_attr (assembly->image, assembly);
10026 idx = 1; /* there is only one assembly */
10027 idx <<= MONO_CUSTOM_ATTR_BITS;
10028 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10029 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10032 static MonoCustomAttrInfo*
10033 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10037 if (image_is_dynamic (image))
10038 return lookup_custom_attr (image, image);
10039 idx = 1; /* there is only one module */
10040 idx <<= MONO_CUSTOM_ATTR_BITS;
10041 idx |= MONO_CUSTOM_ATTR_MODULE;
10042 return mono_custom_attrs_from_index_checked (image, idx, error);
10045 MonoCustomAttrInfo*
10046 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10049 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10050 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10054 MonoCustomAttrInfo*
10055 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10059 if (image_is_dynamic (klass->image)) {
10060 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10061 return lookup_custom_attr (klass->image, property);
10063 idx = find_property_index (klass, property);
10064 idx <<= MONO_CUSTOM_ATTR_BITS;
10065 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10066 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10069 MonoCustomAttrInfo*
10070 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10073 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10074 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10078 MonoCustomAttrInfo*
10079 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10083 if (image_is_dynamic (klass->image)) {
10084 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10085 return lookup_custom_attr (klass->image, event);
10087 idx = find_event_index (klass, event);
10088 idx <<= MONO_CUSTOM_ATTR_BITS;
10089 idx |= MONO_CUSTOM_ATTR_EVENT;
10090 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10093 MonoCustomAttrInfo*
10094 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10097 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10098 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10102 MonoCustomAttrInfo*
10103 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10106 mono_error_init (error);
10108 if (image_is_dynamic (klass->image)) {
10109 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10110 return lookup_custom_attr (klass->image, field);
10112 idx = find_field_index (klass, field);
10113 idx <<= MONO_CUSTOM_ATTR_BITS;
10114 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10115 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10119 * mono_custom_attrs_from_param:
10120 * @method: handle to the method that we want to retrieve custom parameter information from
10121 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10123 * The result must be released with mono_custom_attrs_free().
10125 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10127 MonoCustomAttrInfo*
10128 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10131 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10132 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10137 * mono_custom_attrs_from_param_checked:
10138 * @method: handle to the method that we want to retrieve custom parameter information from
10139 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10140 * @error: set on error
10142 * The result must be released with mono_custom_attrs_free().
10144 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10146 MonoCustomAttrInfo*
10147 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10150 guint32 i, idx, method_index;
10151 guint32 param_list, param_last, param_pos, found;
10153 MonoReflectionMethodAux *aux;
10155 mono_error_init (error);
10158 * An instantiated method has the same cattrs as the generic method definition.
10160 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10161 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10163 if (method->is_inflated)
10164 method = ((MonoMethodInflated *) method)->declaring;
10166 if (image_is_dynamic (method->klass->image)) {
10167 MonoCustomAttrInfo *res, *ainfo;
10170 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10171 if (!aux || !aux->param_cattr)
10174 /* Need to copy since it will be freed later */
10175 ainfo = aux->param_cattr [param];
10178 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10179 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10180 memcpy (res, ainfo, size);
10184 image = method->klass->image;
10185 method_index = mono_method_get_index (method);
10188 ca = &image->tables [MONO_TABLE_METHOD];
10190 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10191 if (method_index == ca->rows) {
10192 ca = &image->tables [MONO_TABLE_PARAM];
10193 param_last = ca->rows + 1;
10195 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10196 ca = &image->tables [MONO_TABLE_PARAM];
10199 for (i = param_list; i < param_last; ++i) {
10200 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10201 if (param_pos == param) {
10209 idx <<= MONO_CUSTOM_ATTR_BITS;
10210 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10211 return mono_custom_attrs_from_index_checked (image, idx, error);
10215 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10219 for (i = 0; i < ainfo->num_attrs; ++i) {
10220 klass = ainfo->attrs [i].ctor->klass;
10221 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10228 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10231 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10232 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10237 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10243 mono_error_init (error);
10246 for (i = 0; i < ainfo->num_attrs; ++i) {
10247 klass = ainfo->attrs [i].ctor->klass;
10248 if (mono_class_has_parent (klass, attr_klass)) {
10253 if (attr_index == -1)
10256 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10257 if (!mono_error_ok (error))
10259 return mono_array_get (attrs, MonoObject*, attr_index);
10263 * mono_reflection_get_custom_attrs_info:
10264 * @obj: a reflection object handle
10266 * Return the custom attribute info for attributes defined for the
10267 * reflection handle @obj. The objects.
10269 * FIXME this function leaks like a sieve for SRE objects.
10271 MonoCustomAttrInfo*
10272 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10275 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10276 mono_error_assert_ok (&error);
10281 * mono_reflection_get_custom_attrs_info_checked:
10282 * @obj: a reflection object handle
10283 * @error: set on error
10285 * Return the custom attribute info for attributes defined for the
10286 * reflection handle @obj. The objects.
10288 * On failure returns NULL and sets @error.
10290 * FIXME this function leaks like a sieve for SRE objects.
10292 MonoCustomAttrInfo*
10293 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10296 MonoCustomAttrInfo *cinfo = NULL;
10298 mono_error_init (error);
10300 klass = obj->vtable->klass;
10301 if (klass == mono_defaults.monotype_class) {
10302 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10303 return_val_if_nok (error, NULL);
10304 klass = mono_class_from_mono_type (type);
10305 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10306 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10307 return_val_if_nok (error, NULL);
10308 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10309 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10310 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10311 return_val_if_nok (error, NULL);
10312 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10313 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10314 cinfo = mono_custom_attrs_from_module (module->image, error);
10315 return_val_if_nok (error, NULL);
10316 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10317 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10318 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10319 return_val_if_nok (error, NULL);
10320 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10321 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10322 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10323 return_val_if_nok (error, NULL);
10324 } else if (strcmp ("MonoField", klass->name) == 0) {
10325 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10326 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10327 return_val_if_nok (error, NULL);
10328 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10329 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10330 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10331 return_val_if_nok (error, NULL);
10332 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10333 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10334 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10335 return_val_if_nok (error, NULL);
10336 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10337 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10338 MonoClass *member_class = mono_object_class (param->MemberImpl);
10339 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10340 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10341 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10342 return_val_if_nok (error, NULL);
10343 } else if (is_sr_mono_property (member_class)) {
10344 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10345 MonoMethod *method;
10346 if (!(method = prop->property->get))
10347 method = prop->property->set;
10350 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10351 return_val_if_nok (error, NULL);
10353 #ifndef DISABLE_REFLECTION_EMIT
10354 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10355 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10356 return_val_if_nok (error, NULL);
10357 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10358 return_val_if_nok (error, NULL);
10359 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10360 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10361 MonoMethod *method = NULL;
10362 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10363 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10364 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10365 method = ((MonoReflectionMethod *)c->cb)->method;
10367 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));
10369 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10370 return_val_if_nok (error, NULL);
10374 char *type_name = mono_type_get_full_name (member_class);
10375 mono_error_set_not_supported (error,
10376 "Custom attributes on a ParamInfo with member %s are not supported",
10378 g_free (type_name);
10381 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10382 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10383 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10384 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10385 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10386 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10387 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10388 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10389 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10390 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10391 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10392 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10393 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10394 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10395 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10396 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10397 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10398 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10399 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10400 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10401 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10402 return_val_if_nok (error, NULL);
10403 } else { /* handle other types here... */
10404 g_error ("get custom attrs not yet supported for %s", klass->name);
10411 * mono_reflection_get_custom_attrs_by_type:
10412 * @obj: a reflection object handle
10414 * Return an array with all the custom attributes defined of the
10415 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10416 * of that type are returned. The objects are fully build. Return NULL if a loading error
10420 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10423 MonoCustomAttrInfo *cinfo;
10425 mono_error_init (error);
10427 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10428 return_val_if_nok (error, NULL);
10430 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10433 if (!cinfo->cached)
10434 mono_custom_attrs_free (cinfo);
10436 mono_loader_assert_no_error ();
10437 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10444 * mono_reflection_get_custom_attrs:
10445 * @obj: a reflection object handle
10447 * Return an array with all the custom attributes defined of the
10448 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10452 mono_reflection_get_custom_attrs (MonoObject *obj)
10456 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10460 * mono_reflection_get_custom_attrs_data:
10461 * @obj: a reflection obj handle
10463 * Returns an array of System.Reflection.CustomAttributeData,
10464 * which include information about attributes reflected on
10465 * types loaded using the Reflection Only methods
10468 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10472 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10473 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10478 * mono_reflection_get_custom_attrs_data_checked:
10479 * @obj: a reflection obj handle
10480 * @error: set on error
10482 * Returns an array of System.Reflection.CustomAttributeData,
10483 * which include information about attributes reflected on
10484 * types loaded using the Reflection Only methods
10487 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10490 MonoCustomAttrInfo *cinfo;
10492 mono_error_init (error);
10494 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10495 return_val_if_nok (error, NULL);
10497 result = mono_custom_attrs_data_construct (cinfo, error);
10498 return_val_if_nok (error, NULL);
10499 if (!cinfo->cached)
10500 mono_custom_attrs_free (cinfo);
10502 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10504 if (mono_loader_get_last_error ())
10505 mono_error_set_from_loader_error (error);
10510 static MonoReflectionType*
10511 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10513 static MonoMethod *method_get_underlying_system_type = NULL;
10514 MonoReflectionType *rt;
10515 MonoMethod *usertype_method;
10517 mono_error_init (error);
10519 if (!method_get_underlying_system_type)
10520 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10522 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10524 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10531 is_corlib_type (MonoClass *klass)
10533 return klass->image == mono_defaults.corlib;
10536 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10537 static MonoClass *cached_class; \
10538 if (cached_class) \
10539 return cached_class == _class; \
10540 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10541 cached_class = _class; \
10548 #ifndef DISABLE_REFLECTION_EMIT
10550 is_sre_array (MonoClass *klass)
10552 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10556 is_sre_byref (MonoClass *klass)
10558 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10562 is_sre_pointer (MonoClass *klass)
10564 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10568 is_sre_generic_instance (MonoClass *klass)
10570 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10574 is_sre_type_builder (MonoClass *klass)
10576 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10580 is_sre_method_builder (MonoClass *klass)
10582 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10586 is_sre_ctor_builder (MonoClass *klass)
10588 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10592 is_sre_field_builder (MonoClass *klass)
10594 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10598 is_sre_method_on_tb_inst (MonoClass *klass)
10600 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10604 is_sre_ctor_on_tb_inst (MonoClass *klass)
10606 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10610 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10613 mono_error_init (error);
10620 if (is_usertype (ref)) {
10621 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10622 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10628 klass = mono_object_class (ref);
10630 if (is_sre_array (klass)) {
10632 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10633 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10634 return_val_if_nok (error, NULL);
10636 if (sre_array->rank == 0) //single dimentional array
10637 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10639 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10640 sre_array->type.type = res;
10642 } else if (is_sre_byref (klass)) {
10644 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10645 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10646 return_val_if_nok (error, NULL);
10648 res = &mono_class_from_mono_type (base)->this_arg;
10649 sre_byref->type.type = res;
10651 } else if (is_sre_pointer (klass)) {
10653 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10654 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10655 return_val_if_nok (error, NULL);
10657 res = &mono_ptr_class_get (base)->byval_arg;
10658 sre_pointer->type.type = res;
10660 } else if (is_sre_generic_instance (klass)) {
10661 MonoType *res, **types;
10662 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10665 count = mono_array_length (gclass->type_arguments);
10666 types = g_new0 (MonoType*, count);
10667 for (i = 0; i < count; ++i) {
10668 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10669 types [i] = mono_reflection_type_get_handle (t, error);
10670 if (!types[i] || !is_ok (error)) {
10676 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10679 gclass->type.type = res;
10683 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10688 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10691 mono_reflection_type_get_handle (type, &error);
10692 mono_error_set_pending_exception (&error);
10696 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10698 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10701 mono_error_init (error);
10703 MonoType *res = mono_reflection_type_get_handle (type, error);
10705 if (!res && is_ok (error)) {
10706 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10708 return_val_if_nok (error, FALSE);
10710 klass = mono_class_from_mono_type (res);
10712 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10713 mono_domain_lock (domain);
10715 if (!image_is_dynamic (klass->image)) {
10716 mono_class_setup_supertypes (klass);
10718 if (!domain->type_hash)
10719 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10720 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10721 mono_g_hash_table_insert (domain->type_hash, res, type);
10723 mono_domain_unlock (domain);
10724 mono_loader_unlock ();
10730 mono_reflection_register_with_runtime (MonoReflectionType *type)
10733 (void) reflection_register_with_runtime (type, &error);
10734 mono_error_set_pending_exception (&error);
10738 * LOCKING: Assumes the loader lock is held.
10740 static MonoMethodSignature*
10741 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10742 MonoMethodSignature *sig;
10745 mono_error_init (error);
10747 count = parameters? mono_array_length (parameters): 0;
10749 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10750 sig->param_count = count;
10751 sig->sentinelpos = -1; /* FIXME */
10752 for (i = 0; i < count; ++i) {
10753 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10754 if (!is_ok (error)) {
10755 image_g_free (image, sig);
10763 * LOCKING: Assumes the loader lock is held.
10765 static MonoMethodSignature*
10766 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10767 MonoMethodSignature *sig;
10769 mono_error_init (error);
10771 sig = parameters_to_signature (image, ctor->parameters, error);
10772 return_val_if_nok (error, NULL);
10773 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10774 sig->ret = &mono_defaults.void_class->byval_arg;
10779 * LOCKING: Assumes the loader lock is held.
10781 static MonoMethodSignature*
10782 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10783 MonoMethodSignature *sig;
10785 mono_error_init (error);
10787 sig = parameters_to_signature (image, method->parameters, error);
10788 return_val_if_nok (error, NULL);
10789 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10790 if (method->rtype) {
10791 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10792 if (!is_ok (error)) {
10793 image_g_free (image, sig);
10797 sig->ret = &mono_defaults.void_class->byval_arg;
10799 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10803 static MonoMethodSignature*
10804 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10805 MonoMethodSignature *sig;
10807 mono_error_init (error);
10809 sig = parameters_to_signature (NULL, method->parameters, error);
10810 return_val_if_nok (error, NULL);
10811 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10812 if (method->rtype) {
10813 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10814 if (!is_ok (error)) {
10819 sig->ret = &mono_defaults.void_class->byval_arg;
10821 sig->generic_param_count = 0;
10826 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10828 mono_error_init (error);
10829 MonoClass *klass = mono_object_class (prop);
10830 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10831 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10832 *name = mono_string_to_utf8 (pb->name);
10833 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10835 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10836 *name = g_strdup (p->property->name);
10837 if (p->property->get)
10838 *type = mono_method_signature (p->property->get)->ret;
10840 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10845 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10847 mono_error_init (error);
10848 MonoClass *klass = mono_object_class (field);
10849 if (strcmp (klass->name, "FieldBuilder") == 0) {
10850 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10851 *name = mono_string_to_utf8 (fb->name);
10852 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10854 MonoReflectionField *f = (MonoReflectionField *)field;
10855 *name = g_strdup (mono_field_get_name (f->field));
10856 *type = f->field->type;
10860 #else /* DISABLE_REFLECTION_EMIT */
10863 mono_reflection_register_with_runtime (MonoReflectionType *type)
10865 /* This is empty */
10869 is_sre_type_builder (MonoClass *klass)
10875 is_sre_generic_instance (MonoClass *klass)
10881 init_type_builder_generics (MonoObject *type)
10885 #endif /* !DISABLE_REFLECTION_EMIT */
10889 is_sr_mono_field (MonoClass *klass)
10891 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10895 is_sr_mono_property (MonoClass *klass)
10897 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10901 is_sr_mono_method (MonoClass *klass)
10903 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10907 is_sr_mono_cmethod (MonoClass *klass)
10909 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10913 is_sr_mono_generic_method (MonoClass *klass)
10915 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10919 is_sr_mono_generic_cmethod (MonoClass *klass)
10921 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10925 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10927 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10931 is_usertype (MonoReflectionType *ref)
10933 MonoClass *klass = mono_object_class (ref);
10934 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10937 static MonoReflectionType*
10938 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10940 mono_error_init (error);
10941 if (!type || type->type)
10944 if (is_usertype (type)) {
10945 type = mono_reflection_type_get_underlying_system_type (type, error);
10946 return_val_if_nok (error, NULL);
10947 if (is_usertype (type)) {
10948 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10956 * encode_cattr_value:
10957 * Encode a value in a custom attribute stream of bytes.
10958 * The value to encode is either supplied as an object in argument val
10959 * (valuetypes are boxed), or as a pointer to the data in the
10961 * @type represents the type of the value
10962 * @buffer is the start of the buffer
10963 * @p the current position in the buffer
10964 * @buflen contains the size of the buffer and is used to return the new buffer size
10965 * if this needs to be realloced.
10966 * @retbuffer and @retp return the start and the position of the buffer
10967 * @error set on error.
10970 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10972 MonoTypeEnum simple_type;
10974 mono_error_init (error);
10975 if ((p-buffer) + 10 >= *buflen) {
10978 newbuf = (char *)g_realloc (buffer, *buflen);
10979 p = newbuf + (p-buffer);
10983 argval = ((char*)arg + sizeof (MonoObject));
10984 simple_type = type->type;
10986 switch (simple_type) {
10987 case MONO_TYPE_BOOLEAN:
10992 case MONO_TYPE_CHAR:
10995 swap_with_size (p, argval, 2, 1);
11001 swap_with_size (p, argval, 4, 1);
11005 swap_with_size (p, argval, 8, 1);
11010 swap_with_size (p, argval, 8, 1);
11013 case MONO_TYPE_VALUETYPE:
11014 if (type->data.klass->enumtype) {
11015 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11018 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11021 case MONO_TYPE_STRING: {
11028 str = mono_string_to_utf8 ((MonoString*)arg);
11029 slen = strlen (str);
11030 if ((p-buffer) + 10 + slen >= *buflen) {
11034 newbuf = (char *)g_realloc (buffer, *buflen);
11035 p = newbuf + (p-buffer);
11038 mono_metadata_encode_value (slen, p, &p);
11039 memcpy (p, str, slen);
11044 case MONO_TYPE_CLASS: {
11047 MonoType *arg_type;
11053 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11054 return_if_nok (error);
11056 str = type_get_qualified_name (arg_type, NULL);
11057 slen = strlen (str);
11058 if ((p-buffer) + 10 + slen >= *buflen) {
11062 newbuf = (char *)g_realloc (buffer, *buflen);
11063 p = newbuf + (p-buffer);
11066 mono_metadata_encode_value (slen, p, &p);
11067 memcpy (p, str, slen);
11072 case MONO_TYPE_SZARRAY: {
11074 MonoClass *eclass, *arg_eclass;
11077 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11080 len = mono_array_length ((MonoArray*)arg);
11082 *p++ = (len >> 8) & 0xff;
11083 *p++ = (len >> 16) & 0xff;
11084 *p++ = (len >> 24) & 0xff;
11086 *retbuffer = buffer;
11087 eclass = type->data.klass;
11088 arg_eclass = mono_object_class (arg)->element_class;
11091 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11092 eclass = mono_defaults.object_class;
11094 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11095 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11096 int elsize = mono_class_array_element_size (arg_eclass);
11097 for (i = 0; i < len; ++i) {
11098 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11099 return_if_nok (error);
11102 } else if (eclass->valuetype && arg_eclass->valuetype) {
11103 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11104 int elsize = mono_class_array_element_size (eclass);
11105 for (i = 0; i < len; ++i) {
11106 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11107 return_if_nok (error);
11111 for (i = 0; i < len; ++i) {
11112 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11113 return_if_nok (error);
11118 case MONO_TYPE_OBJECT: {
11124 * The parameter type is 'object' but the type of the actual
11125 * argument is not. So we have to add type information to the blob
11126 * too. This is completely undocumented in the spec.
11130 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11135 klass = mono_object_class (arg);
11137 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11141 return_if_nok (error);
11144 if (klass->enumtype) {
11146 } else if (klass == mono_defaults.string_class) {
11147 simple_type = MONO_TYPE_STRING;
11150 } else if (klass->rank == 1) {
11152 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11153 /* See Partition II, Appendix B3 */
11156 *p++ = klass->element_class->byval_arg.type;
11157 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11158 return_if_nok (error);
11160 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11161 *p++ = simple_type = klass->byval_arg.type;
11164 g_error ("unhandled type in custom attr");
11166 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11167 slen = strlen (str);
11168 if ((p-buffer) + 10 + slen >= *buflen) {
11172 newbuf = (char *)g_realloc (buffer, *buflen);
11173 p = newbuf + (p-buffer);
11176 mono_metadata_encode_value (slen, p, &p);
11177 memcpy (p, str, slen);
11180 simple_type = mono_class_enum_basetype (klass)->type;
11184 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11187 *retbuffer = buffer;
11191 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11193 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11194 char *str = type_get_qualified_name (type, NULL);
11195 int slen = strlen (str);
11199 * This seems to be optional...
11202 mono_metadata_encode_value (slen, p, &p);
11203 memcpy (p, str, slen);
11206 } else if (type->type == MONO_TYPE_OBJECT) {
11208 } else if (type->type == MONO_TYPE_CLASS) {
11209 /* it should be a type: encode_cattr_value () has the check */
11212 mono_metadata_encode_value (type->type, p, &p);
11213 if (type->type == MONO_TYPE_SZARRAY)
11214 /* See the examples in Partition VI, Annex B */
11215 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11221 #ifndef DISABLE_REFLECTION_EMIT
11223 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11227 mono_error_init (error);
11229 /* Preallocate a large enough buffer */
11230 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11231 char *str = type_get_qualified_name (type, NULL);
11232 len = strlen (str);
11234 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11235 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11236 len = strlen (str);
11241 len += strlen (name);
11243 if ((p-buffer) + 20 + len >= *buflen) {
11247 newbuf = (char *)g_realloc (buffer, *buflen);
11248 p = newbuf + (p-buffer);
11252 encode_field_or_prop_type (type, p, &p);
11254 len = strlen (name);
11255 mono_metadata_encode_value (len, p, &p);
11256 memcpy (p, name, len);
11258 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11259 return_if_nok (error);
11261 *retbuffer = buffer;
11265 * mono_reflection_get_custom_attrs_blob:
11266 * @ctor: custom attribute constructor
11267 * @ctorArgs: arguments o the constructor
11273 * Creates the blob of data that needs to be saved in the metadata and that represents
11274 * the custom attributed described by @ctor, @ctorArgs etc.
11275 * Returns: a Byte array representing the blob of data.
11278 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11281 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11282 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11287 * mono_reflection_get_custom_attrs_blob_checked:
11288 * @ctor: custom attribute constructor
11289 * @ctorArgs: arguments o the constructor
11294 * @error: set on error
11296 * Creates the blob of data that needs to be saved in the metadata and that represents
11297 * the custom attributed described by @ctor, @ctorArgs etc.
11298 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11301 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11303 MonoArray *result = NULL;
11304 MonoMethodSignature *sig;
11309 mono_error_init (error);
11311 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11312 /* sig is freed later so allocate it in the heap */
11313 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11314 if (!is_ok (error)) {
11319 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11322 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11324 p = buffer = (char *)g_malloc (buflen);
11325 /* write the prolog */
11328 for (i = 0; i < sig->param_count; ++i) {
11329 arg = mono_array_get (ctorArgs, MonoObject*, i);
11330 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11331 if (!is_ok (error)) goto leave;
11335 i += mono_array_length (properties);
11337 i += mono_array_length (fields);
11339 *p++ = (i >> 8) & 0xff;
11342 for (i = 0; i < mono_array_length (properties); ++i) {
11346 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11347 get_prop_name_and_type (prop, &pname, &ptype, error);
11348 if (!is_ok (error)) goto leave;
11349 *p++ = 0x54; /* PROPERTY signature */
11350 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11352 if (!is_ok (error)) goto leave;
11358 for (i = 0; i < mono_array_length (fields); ++i) {
11362 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11363 get_field_name_and_type (field, &fname, &ftype, error);
11364 if (!is_ok (error)) goto leave;
11365 *p++ = 0x53; /* FIELD signature */
11366 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11368 if (!is_ok (error)) goto leave;
11372 g_assert (p - buffer <= buflen);
11373 buflen = p - buffer;
11374 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11375 p = mono_array_addr (result, char, 0);
11376 memcpy (p, buffer, buflen);
11379 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11385 * reflection_setup_internal_class:
11386 * @tb: a TypeBuilder object
11387 * @error: set on error
11389 * Creates a MonoClass that represents the TypeBuilder.
11390 * This is a trick that lets us simplify a lot of reflection code
11391 * (and will allow us to support Build and Run assemblies easier).
11393 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11396 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11398 MonoClass *klass, *parent;
11400 mono_error_init (error);
11401 RESOLVE_TYPE (tb->parent, error);
11402 return_val_if_nok (error, FALSE);
11404 mono_loader_lock ();
11407 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11408 if (!is_ok (error)) {
11409 mono_loader_unlock ();
11412 /* check so we can compile corlib correctly */
11413 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11414 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11415 parent = parent_type->data.klass;
11417 parent = mono_class_from_mono_type (parent_type);
11423 /* the type has already being created: it means we just have to change the parent */
11424 if (tb->type.type) {
11425 klass = mono_class_from_mono_type (tb->type.type);
11426 klass->parent = NULL;
11427 /* fool mono_class_setup_parent */
11428 klass->supertypes = NULL;
11429 mono_class_setup_parent (klass, parent);
11430 mono_class_setup_mono_type (klass);
11431 mono_loader_unlock ();
11435 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11437 klass->image = &tb->module->dynamic_image->image;
11439 klass->inited = 1; /* we lie to the runtime */
11440 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11441 if (!is_ok (error))
11443 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11444 if (!is_ok (error))
11446 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11447 klass->flags = tb->attrs;
11449 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11451 klass->element_class = klass;
11453 if (mono_class_get_ref_info (klass) == NULL) {
11455 mono_class_set_ref_info (klass, tb);
11457 /* Put into cache so mono_class_get_checked () will find it.
11458 Skip nested types as those should not be available on the global scope. */
11459 if (!tb->nesting_type)
11460 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11463 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11464 by performing a mono_class_get which does the full resolution.
11466 Working around this semantics would require us to write a lot of code for no clear advantage.
11468 mono_image_append_class_to_reflection_info_set (klass);
11470 g_assert (mono_class_get_ref_info (klass) == tb);
11473 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11475 if (parent != NULL) {
11476 mono_class_setup_parent (klass, parent);
11477 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11478 const char *old_n = klass->name;
11479 /* trick to get relative numbering right when compiling corlib */
11480 klass->name = "BuildingObject";
11481 mono_class_setup_parent (klass, mono_defaults.object_class);
11482 klass->name = old_n;
11485 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11486 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11487 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11488 klass->instance_size = sizeof (MonoObject);
11489 klass->size_inited = 1;
11490 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11493 mono_class_setup_mono_type (klass);
11495 mono_class_setup_supertypes (klass);
11498 * FIXME: handle interfaces.
11501 tb->type.type = &klass->byval_arg;
11503 if (tb->nesting_type) {
11504 g_assert (tb->nesting_type->type);
11505 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11506 if (!is_ok (error)) goto failure;
11507 klass->nested_in = mono_class_from_mono_type (nesting_type);
11510 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11512 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11514 mono_loader_unlock ();
11518 mono_loader_unlock ();
11523 * mono_reflection_setup_internal_class:
11524 * @tb: a TypeBuilder object
11527 * Creates a MonoClass that represents the TypeBuilder.
11528 * This is a trick that lets us simplify a lot of reflection code
11529 * (and will allow us to support Build and Run assemblies easier).
11533 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11536 (void) reflection_setup_internal_class (tb, &error);
11537 mono_error_set_pending_exception (&error);
11541 * mono_reflection_setup_generic_class:
11542 * @tb: a TypeBuilder object
11544 * Setup the generic class before adding the first generic parameter.
11547 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11552 * mono_reflection_create_generic_class:
11553 * @tb: a TypeBuilder object
11555 * Creates the generic class after all generic parameters have been added.
11558 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11564 klass = mono_class_from_mono_type (tb->type.type);
11566 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11568 if (klass->generic_container || (count == 0))
11571 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11573 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11575 klass->generic_container->owner.klass = klass;
11576 klass->generic_container->type_argc = count;
11577 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11579 klass->is_generic = 1;
11581 for (i = 0; i < count; i++) {
11582 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11583 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11584 mono_error_raise_exception (&error); /* FIXME don't raise here */
11585 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11586 klass->generic_container->type_params [i] = *param;
11587 /*Make sure we are a diferent type instance */
11588 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11589 klass->generic_container->type_params [i].info.pklass = NULL;
11590 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11592 g_assert (klass->generic_container->type_params [i].param.owner);
11595 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11599 * reflection_create_internal_class:
11600 * @tb: a TypeBuilder object
11601 * @error: set on error
11603 * Actually create the MonoClass that is associated with the TypeBuilder.
11604 * On success returns TRUE, on failure returns FALSE and sets @error.
11608 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11613 mono_error_init (error);
11614 klass = mono_class_from_mono_type (tb->type.type);
11616 mono_loader_lock ();
11617 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11618 MonoReflectionFieldBuilder *fb;
11620 MonoType *enum_basetype;
11622 g_assert (tb->fields != NULL);
11623 g_assert (mono_array_length (tb->fields) >= 1);
11625 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11627 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11628 if (!is_ok (error)) {
11629 mono_loader_unlock ();
11632 if (!mono_type_is_valid_enum_basetype (field_type)) {
11633 mono_loader_unlock ();
11637 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11638 if (!is_ok (error)) {
11639 mono_loader_unlock ();
11642 klass->element_class = mono_class_from_mono_type (enum_basetype);
11643 if (!klass->element_class)
11644 klass->element_class = mono_class_from_mono_type (enum_basetype);
11647 * get the element_class from the current corlib.
11649 ec = default_class_from_mono_type (enum_basetype);
11650 klass->instance_size = ec->instance_size;
11651 klass->size_inited = 1;
11653 * this is almost safe to do with enums and it's needed to be able
11654 * to create objects of the enum type (for use in SetConstant).
11656 /* FIXME: Does this mean enums can't have method overrides ? */
11657 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11659 mono_loader_unlock ();
11664 * mono_reflection_create_internal_class:
11665 * @tb: a TypeBuilder object
11668 * Actually create the MonoClass that is associated with the TypeBuilder.
11671 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11674 (void) reflection_create_internal_class (tb, &error);
11675 mono_error_set_pending_exception (&error);
11678 static MonoMarshalSpec*
11679 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11680 MonoReflectionMarshal *minfo, MonoError *error)
11682 MonoMarshalSpec *res;
11684 mono_error_init (error);
11686 res = image_g_new0 (image, MonoMarshalSpec, 1);
11687 res->native = (MonoMarshalNative)minfo->type;
11689 switch (minfo->type) {
11690 case MONO_NATIVE_LPARRAY:
11691 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11692 if (minfo->has_size) {
11693 res->data.array_data.param_num = minfo->param_num;
11694 res->data.array_data.num_elem = minfo->count;
11695 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11698 res->data.array_data.param_num = -1;
11699 res->data.array_data.num_elem = -1;
11700 res->data.array_data.elem_mult = -1;
11704 case MONO_NATIVE_BYVALTSTR:
11705 case MONO_NATIVE_BYVALARRAY:
11706 res->data.array_data.num_elem = minfo->count;
11709 case MONO_NATIVE_CUSTOM:
11710 if (minfo->marshaltyperef) {
11711 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11712 if (!is_ok (error)) {
11713 image_g_free (image, res);
11716 res->data.custom_data.custom_name =
11717 type_get_fully_qualified_name (marshaltyperef);
11719 if (minfo->mcookie)
11720 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11729 #endif /* !DISABLE_REFLECTION_EMIT */
11731 MonoReflectionMarshalAsAttribute*
11732 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11733 MonoMarshalSpec *spec, MonoError *error)
11735 MonoReflectionType *rt;
11736 MonoReflectionMarshalAsAttribute *minfo;
11739 mono_error_init (error);
11741 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11744 minfo->utype = spec->native;
11746 switch (minfo->utype) {
11747 case MONO_NATIVE_LPARRAY:
11748 minfo->array_subtype = spec->data.array_data.elem_type;
11749 minfo->size_const = spec->data.array_data.num_elem;
11750 if (spec->data.array_data.param_num != -1)
11751 minfo->size_param_index = spec->data.array_data.param_num;
11754 case MONO_NATIVE_BYVALTSTR:
11755 case MONO_NATIVE_BYVALARRAY:
11756 minfo->size_const = spec->data.array_data.num_elem;
11759 case MONO_NATIVE_CUSTOM:
11760 if (spec->data.custom_data.custom_name) {
11761 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11762 return_val_if_nok (error, NULL);
11765 rt = mono_type_get_object_checked (domain, mtype, error);
11769 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11772 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11774 if (spec->data.custom_data.cookie)
11775 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11785 #ifndef DISABLE_REFLECTION_EMIT
11787 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11788 ReflectionMethodBuilder *rmb,
11789 MonoMethodSignature *sig)
11793 MonoMethodWrapper *wrapperm;
11794 MonoMarshalSpec **specs;
11795 MonoReflectionMethodAux *method_aux;
11800 mono_error_init (&error);
11802 * Methods created using a MethodBuilder should have their memory allocated
11803 * inside the image mempool, while dynamic methods should have their memory
11806 dynamic = rmb->refs != NULL;
11807 image = dynamic ? NULL : klass->image;
11810 g_assert (!klass->generic_class);
11812 mono_loader_lock ();
11814 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11815 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11816 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11818 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11820 wrapperm = (MonoMethodWrapper*)m;
11822 m->dynamic = dynamic;
11824 m->flags = rmb->attrs;
11825 m->iflags = rmb->iattrs;
11826 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11828 m->signature = sig;
11829 m->sre_method = TRUE;
11830 m->skip_visibility = rmb->skip_visibility;
11831 if (rmb->table_idx)
11832 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11834 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11835 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11836 m->string_ctor = 1;
11838 m->signature->pinvoke = 1;
11839 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11840 m->signature->pinvoke = 1;
11842 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11844 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11845 g_assert (mono_error_ok (&error));
11846 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11847 g_assert (mono_error_ok (&error));
11849 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11851 if (image_is_dynamic (klass->image))
11852 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11854 mono_loader_unlock ();
11857 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11858 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11859 MonoMethodHeader *header;
11861 gint32 max_stack, i;
11862 gint32 num_locals = 0;
11863 gint32 num_clauses = 0;
11867 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11868 code_size = rmb->ilgen->code_len;
11869 max_stack = rmb->ilgen->max_stack;
11870 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11871 if (rmb->ilgen->ex_handlers)
11872 num_clauses = method_count_clauses (rmb->ilgen);
11875 code = mono_array_addr (rmb->code, guint8, 0);
11876 code_size = mono_array_length (rmb->code);
11877 /* we probably need to run a verifier on the code... */
11887 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11888 header->code_size = code_size;
11889 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11890 memcpy ((char*)header->code, code, code_size);
11891 header->max_stack = max_stack;
11892 header->init_locals = rmb->init_locals;
11893 header->num_locals = num_locals;
11895 for (i = 0; i < num_locals; ++i) {
11896 MonoReflectionLocalBuilder *lb =
11897 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11899 header->locals [i] = image_g_new0 (image, MonoType, 1);
11900 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11901 mono_error_assert_ok (&error);
11902 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11905 header->num_clauses = num_clauses;
11907 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11908 rmb->ilgen, num_clauses, &error);
11909 mono_error_assert_ok (&error);
11912 wrapperm->header = header;
11915 if (rmb->generic_params) {
11916 int count = mono_array_length (rmb->generic_params);
11917 MonoGenericContainer *container = rmb->generic_container;
11919 g_assert (container);
11921 container->type_argc = count;
11922 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11923 container->owner.method = m;
11924 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11926 m->is_generic = TRUE;
11927 mono_method_set_generic_container (m, container);
11929 for (i = 0; i < count; i++) {
11930 MonoReflectionGenericParam *gp =
11931 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11932 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11933 mono_error_assert_ok (&error);
11934 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11935 container->type_params [i] = *param;
11939 * The method signature might have pointers to generic parameters that belong to other methods.
11940 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11941 * generic parameters.
11943 for (i = 0; i < m->signature->param_count; ++i) {
11944 MonoType *t = m->signature->params [i];
11945 if (t->type == MONO_TYPE_MVAR) {
11946 MonoGenericParam *gparam = t->data.generic_param;
11947 if (gparam->num < count) {
11948 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11949 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11955 if (klass->generic_container) {
11956 container->parent = klass->generic_container;
11957 container->context.class_inst = klass->generic_container->context.class_inst;
11959 container->context.method_inst = mono_get_shared_generic_inst (container);
11963 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11967 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11969 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11970 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11971 for (i = 0; i < rmb->nrefs; ++i)
11972 data [i + 1] = rmb->refs [i];
11977 /* Parameter info */
11980 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11981 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11982 for (i = 0; i <= m->signature->param_count; ++i) {
11983 MonoReflectionParamBuilder *pb;
11984 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11985 if ((i > 0) && (pb->attrs)) {
11986 /* Make a copy since it might point to a shared type structure */
11987 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11988 m->signature->params [i - 1]->attrs = pb->attrs;
11991 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11992 MonoDynamicImage *assembly;
11994 MonoTypeEnum def_type;
11998 if (!method_aux->param_defaults) {
11999 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12000 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12002 assembly = (MonoDynamicImage*)klass->image;
12003 idx = encode_constant (assembly, pb->def_value, &def_type);
12004 /* Copy the data from the blob since it might get realloc-ed */
12005 p = assembly->blob.data + idx;
12006 len = mono_metadata_decode_blob_size (p, &p2);
12008 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12009 method_aux->param_default_types [i] = def_type;
12010 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12014 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12015 g_assert (mono_error_ok (&error));
12018 if (!method_aux->param_cattr)
12019 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12020 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12026 /* Parameter marshalling */
12029 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12030 MonoReflectionParamBuilder *pb;
12031 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12032 if (pb->marshal_info) {
12034 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12035 specs [pb->position] =
12036 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12037 if (!is_ok (&error)) {
12038 mono_loader_unlock ();
12039 image_g_free (image, specs);
12040 mono_error_raise_exception (&error); /* FIXME don't raise here */
12045 if (specs != NULL) {
12047 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12048 method_aux->param_marshall = specs;
12051 if (image_is_dynamic (klass->image) && method_aux)
12052 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12054 mono_loader_unlock ();
12060 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12062 ReflectionMethodBuilder rmb;
12063 MonoMethodSignature *sig;
12065 mono_loader_lock ();
12066 g_assert (klass->image != NULL);
12067 sig = ctor_builder_to_signature (klass->image, mb, error);
12068 mono_loader_unlock ();
12069 return_val_if_nok (error, NULL);
12071 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12074 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12075 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12077 /* If we are in a generic class, we might be called multiple times from inflate_method */
12078 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12079 /* ilgen is no longer needed */
12083 return mb->mhandle;
12087 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12089 ReflectionMethodBuilder rmb;
12090 MonoMethodSignature *sig;
12092 mono_error_init (error);
12094 mono_loader_lock ();
12095 g_assert (klass->image != NULL);
12096 sig = method_builder_to_signature (klass->image, mb, error);
12097 mono_loader_unlock ();
12098 return_val_if_nok (error, NULL);
12100 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12103 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12104 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12106 /* If we are in a generic class, we might be called multiple times from inflate_method */
12107 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12108 /* ilgen is no longer needed */
12111 return mb->mhandle;
12114 static MonoClassField*
12115 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12117 MonoClassField *field;
12120 mono_error_init (error);
12122 field = g_new0 (MonoClassField, 1);
12124 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12125 mono_error_assert_ok (error);
12126 if (fb->attrs || fb->modreq || fb->modopt) {
12127 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12128 if (!is_ok (error)) {
12132 field->type = mono_metadata_type_dup (NULL, type);
12133 field->type->attrs = fb->attrs;
12135 g_assert (image_is_dynamic (klass->image));
12136 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12137 g_free (field->type);
12138 if (!is_ok (error)) {
12142 field->type = mono_metadata_type_dup (klass->image, custom);
12145 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12146 if (!is_ok (error)) {
12151 if (fb->offset != -1)
12152 field->offset = fb->offset;
12153 field->parent = klass;
12154 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12156 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12163 * mono_reflection_bind_generic_parameters:
12164 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12165 * @type_args: the number of type arguments to bind
12166 * @types: array of type arguments
12167 * @error: set on error
12169 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12170 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12173 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12176 MonoReflectionTypeBuilder *tb = NULL;
12177 gboolean is_dynamic = FALSE;
12178 MonoClass *geninst;
12180 mono_error_init (error);
12182 mono_loader_lock ();
12184 if (is_sre_type_builder (mono_object_class (type))) {
12185 tb = (MonoReflectionTypeBuilder *) type;
12188 } else if (is_sre_generic_instance (mono_object_class (type))) {
12189 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12190 MonoReflectionType *gtd = rgi->generic_type;
12192 if (is_sre_type_builder (mono_object_class (gtd))) {
12193 tb = (MonoReflectionTypeBuilder *)gtd;
12198 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12199 if (tb && tb->generic_container)
12200 mono_reflection_create_generic_class (tb);
12202 MonoType *t = mono_reflection_type_get_handle (type, error);
12203 if (!is_ok (error)) {
12204 mono_loader_unlock ();
12208 klass = mono_class_from_mono_type (t);
12209 if (!klass->generic_container) {
12210 mono_loader_unlock ();
12211 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12215 if (klass->wastypebuilder) {
12216 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12221 mono_loader_unlock ();
12223 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12225 return &geninst->byval_arg;
12229 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12231 MonoGenericClass *gclass;
12232 MonoGenericInst *inst;
12234 g_assert (klass->generic_container);
12236 inst = mono_metadata_get_generic_inst (type_argc, types);
12237 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12239 return mono_generic_class_get_class (gclass);
12242 MonoReflectionMethod*
12243 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12247 MonoMethod *method, *inflated;
12248 MonoMethodInflated *imethod;
12249 MonoGenericContext tmp_context;
12250 MonoGenericInst *ginst;
12251 MonoType **type_argv;
12254 /*FIXME but this no longer should happen*/
12255 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12256 #ifndef DISABLE_REFLECTION_EMIT
12257 MonoReflectionMethodBuilder *mb = NULL;
12261 mb = (MonoReflectionMethodBuilder *) rmethod;
12262 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12263 mono_error_raise_exception (&error); /* FIXME don't raise here */
12264 klass = mono_class_from_mono_type (tb);
12266 method = methodbuilder_to_mono_method (klass, mb, &error);
12268 mono_error_raise_exception (&error); /* FIXME don't raise here */
12270 g_assert_not_reached ();
12274 method = rmethod->method;
12277 klass = method->klass;
12279 if (method->is_inflated)
12280 method = ((MonoMethodInflated *) method)->declaring;
12282 count = mono_method_signature (method)->generic_param_count;
12283 if (count != mono_array_length (types))
12286 type_argv = g_new0 (MonoType *, count);
12287 for (i = 0; i < count; i++) {
12288 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12289 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12290 if (!is_ok (&error)) {
12291 g_free (type_argv);
12292 mono_error_raise_exception (&error); /* FIXME don't raise here */
12295 ginst = mono_metadata_get_generic_inst (count, type_argv);
12296 g_free (type_argv);
12298 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12299 tmp_context.method_inst = ginst;
12301 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12302 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12303 imethod = (MonoMethodInflated *) inflated;
12305 /*FIXME but I think this is no longer necessary*/
12306 if (image_is_dynamic (method->klass->image)) {
12307 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12309 * This table maps metadata structures representing inflated methods/fields
12310 * to the reflection objects representing their generic definitions.
12312 mono_image_lock ((MonoImage*)image);
12313 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12314 mono_image_unlock ((MonoImage*)image);
12317 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12318 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12320 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12321 mono_error_raise_exception (&error); /* FIXME don't raise here */
12325 #ifndef DISABLE_REFLECTION_EMIT
12327 static MonoMethod *
12328 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12330 MonoMethodInflated *imethod;
12331 MonoGenericContext *context;
12335 * With generic code sharing the klass might not be inflated.
12336 * This can happen because classes inflated with their own
12337 * type arguments are "normalized" to the uninflated class.
12339 if (!klass->generic_class)
12342 context = mono_class_get_context (klass);
12344 if (klass->method.count && klass->methods) {
12345 /* Find the already created inflated method */
12346 for (i = 0; i < klass->method.count; ++i) {
12347 g_assert (klass->methods [i]->is_inflated);
12348 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12351 g_assert (i < klass->method.count);
12352 imethod = (MonoMethodInflated*)klass->methods [i];
12355 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12356 mono_error_assert_ok (&error);
12359 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12360 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12362 mono_image_lock ((MonoImage*)image);
12363 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12364 mono_image_unlock ((MonoImage*)image);
12366 return (MonoMethod *) imethod;
12369 static MonoMethod *
12370 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12372 MonoMethod *method;
12375 mono_error_init (error);
12377 MonoClass *type_class = mono_object_class (type);
12379 if (is_sre_generic_instance (type_class)) {
12380 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12381 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12382 return_val_if_nok (error, NULL);
12383 gklass = mono_class_from_mono_type (generic_type);
12384 } else if (is_sre_type_builder (type_class)) {
12385 MonoType *t = mono_reflection_type_get_handle (type, error);
12386 return_val_if_nok (error, NULL);
12387 gklass = mono_class_from_mono_type (t);
12388 } else if (type->type) {
12389 gklass = mono_class_from_mono_type (type->type);
12390 gklass = mono_class_get_generic_type_definition (gklass);
12392 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12395 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12396 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12397 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12399 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12403 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12404 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12407 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12408 method = ((MonoReflectionMethod *) obj)->method;
12410 method = NULL; /* prevent compiler warning */
12411 g_error ("can't handle type %s", obj->vtable->klass->name);
12414 MonoType *t = mono_reflection_type_get_handle (type, error);
12415 return_val_if_nok (error, NULL);
12416 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12419 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12421 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12423 MonoGenericClass *gclass;
12424 MonoDynamicGenericClass *dgclass;
12425 MonoClass *klass, *gklass;
12429 mono_error_init (error);
12431 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12432 return_val_if_nok (error, FALSE);
12433 klass = mono_class_from_mono_type (gtype);
12434 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12435 gclass = gtype->data.generic_class;
12437 if (!gclass->is_dynamic)
12440 dgclass = (MonoDynamicGenericClass *) gclass;
12442 if (dgclass->initialized)
12445 gklass = gclass->container_class;
12446 mono_class_init (gklass);
12448 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12450 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12451 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12452 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12454 for (i = 0; i < dgclass->count_fields; i++) {
12455 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12456 MonoClassField *field, *inflated_field = NULL;
12458 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12459 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12460 return_val_if_nok (error, FALSE);
12461 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12462 field = ((MonoReflectionField *) obj)->field;
12464 field = NULL; /* prevent compiler warning */
12465 g_assert_not_reached ();
12468 dgclass->fields [i] = *field;
12469 dgclass->fields [i].parent = klass;
12470 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12471 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12472 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12473 dgclass->field_generic_types [i] = field->type;
12474 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12475 dgclass->field_objects [i] = obj;
12477 if (inflated_field) {
12478 g_free (inflated_field);
12480 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12484 dgclass->initialized = TRUE;
12489 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12492 (void) reflection_generic_class_initialize (type, fields, &error);
12493 mono_error_set_pending_exception (&error);
12497 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12499 MonoDynamicGenericClass *dgclass;
12502 g_assert (gclass->is_dynamic);
12504 dgclass = (MonoDynamicGenericClass *)gclass;
12506 for (i = 0; i < dgclass->count_fields; ++i) {
12507 MonoClassField *field = dgclass->fields + i;
12508 mono_metadata_free_type (field->type);
12509 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12514 * fix_partial_generic_class:
12515 * @klass: a generic instantiation MonoClass
12516 * @error: set on error
12518 * Assumes that the generic container of @klass has its vtable
12519 * initialized, and updates the parent class, insterfaces, methods and
12520 * fields of @klass by inflating the types using the generic context.
12522 * On success returns TRUE, on failure returns FALSE and sets @error.
12526 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12528 MonoClass *gklass = klass->generic_class->container_class;
12529 MonoDynamicGenericClass *dgclass;
12532 mono_error_init (error);
12534 if (klass->wastypebuilder)
12537 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12538 if (klass->parent != gklass->parent) {
12539 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12540 if (mono_error_ok (error)) {
12541 MonoClass *parent = mono_class_from_mono_type (parent_type);
12542 mono_metadata_free_type (parent_type);
12543 if (parent != klass->parent) {
12544 /*fool mono_class_setup_parent*/
12545 klass->supertypes = NULL;
12546 mono_class_setup_parent (klass, parent);
12549 if (gklass->wastypebuilder)
12550 klass->wastypebuilder = TRUE;
12555 if (!dgclass->initialized)
12558 if (klass->method.count != gklass->method.count) {
12559 klass->method.count = gklass->method.count;
12560 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12562 for (i = 0; i < klass->method.count; i++) {
12563 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12564 gklass->methods [i], klass, mono_class_get_context (klass), error);
12565 mono_error_assert_ok (error);
12569 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12570 klass->interface_count = gklass->interface_count;
12571 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12572 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12574 for (i = 0; i < gklass->interface_count; ++i) {
12575 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12576 return_val_if_nok (error, FALSE);
12578 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12579 mono_metadata_free_type (iface_type);
12581 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12584 klass->interfaces_inited = 1;
12587 if (klass->field.count != gklass->field.count) {
12588 klass->field.count = gklass->field.count;
12589 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12591 for (i = 0; i < klass->field.count; i++) {
12592 klass->fields [i] = gklass->fields [i];
12593 klass->fields [i].parent = klass;
12594 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12595 return_val_if_nok (error, FALSE);
12599 /*We can only finish with this klass once it's parent has as well*/
12600 if (gklass->wastypebuilder)
12601 klass->wastypebuilder = TRUE;
12606 * ensure_generic_class_runtime_vtable:
12607 * @klass a generic class
12608 * @error set on error
12610 * Ensures that the generic container of @klass has a vtable and
12611 * returns TRUE on success. On error returns FALSE and sets @error.
12614 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12616 MonoClass *gklass = klass->generic_class->container_class;
12618 mono_error_init (error);
12620 if (!ensure_runtime_vtable (gklass, error))
12623 return fix_partial_generic_class (klass, error);
12627 * ensure_runtime_vtable:
12629 * @error set on error
12631 * Ensures that @klass has a vtable and returns TRUE on success. On
12632 * error returns FALSE and sets @error.
12635 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12637 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12640 mono_error_init (error);
12642 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12645 if (!ensure_runtime_vtable (klass->parent, error))
12649 num = tb->ctors? mono_array_length (tb->ctors): 0;
12650 num += tb->num_methods;
12651 klass->method.count = num;
12652 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12653 num = tb->ctors? mono_array_length (tb->ctors): 0;
12654 for (i = 0; i < num; ++i) {
12655 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12658 klass->methods [i] = ctor;
12660 num = tb->num_methods;
12662 for (i = 0; i < num; ++i) {
12663 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12666 klass->methods [j++] = meth;
12669 if (tb->interfaces) {
12670 klass->interface_count = mono_array_length (tb->interfaces);
12671 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12672 for (i = 0; i < klass->interface_count; ++i) {
12673 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12674 return_val_if_nok (error, FALSE);
12675 klass->interfaces [i] = mono_class_from_mono_type (iface);
12676 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12679 klass->interfaces_inited = 1;
12681 } else if (klass->generic_class){
12682 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12683 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12688 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12690 for (i = 0; i < klass->method.count; ++i) {
12691 MonoMethod *im = klass->methods [i];
12692 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12693 im->slot = slot_num++;
12696 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12697 mono_class_setup_interface_offsets (klass);
12698 mono_class_setup_interface_id (klass);
12702 * The generic vtable is needed even if image->run is not set since some
12703 * runtime code like ves_icall_Type_GetMethodsByName depends on
12704 * method->slot being defined.
12708 * tb->methods could not be freed since it is used for determining
12709 * overrides during dynamic vtable construction.
12716 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12718 mono_error_init (error);
12719 MonoClass *klass = mono_object_class (method);
12720 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12721 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12722 return sr_method->method;
12724 if (is_sre_method_builder (klass)) {
12725 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12726 return mb->mhandle;
12728 if (is_sre_method_on_tb_inst (klass)) {
12729 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12730 MonoMethod *result;
12731 /*FIXME move this to a proper method and unify with resolve_object*/
12732 if (m->method_args) {
12733 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12735 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12736 return_val_if_nok (error, NULL);
12737 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12738 MonoMethod *mono_method;
12740 if (is_sre_method_builder (mono_object_class (m->mb)))
12741 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12742 else if (is_sr_mono_method (mono_object_class (m->mb)))
12743 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12745 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)));
12747 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12752 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12757 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12759 MonoReflectionTypeBuilder *tb;
12761 MonoReflectionMethod *m;
12763 mono_error_init (error);
12765 *num_overrides = 0;
12767 g_assert (image_is_dynamic (klass->image));
12769 if (!mono_class_get_ref_info (klass))
12772 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12774 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12778 for (i = 0; i < tb->num_methods; ++i) {
12779 MonoReflectionMethodBuilder *mb =
12780 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12781 if (mb->override_methods)
12782 onum += mono_array_length (mb->override_methods);
12787 *overrides = g_new0 (MonoMethod*, onum * 2);
12790 for (i = 0; i < tb->num_methods; ++i) {
12791 MonoReflectionMethodBuilder *mb =
12792 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12793 if (mb->override_methods) {
12794 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12795 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12797 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12798 return_if_nok (error);
12799 (*overrides) [onum * 2 + 1] = mb->mhandle;
12801 g_assert (mb->mhandle);
12809 *num_overrides = onum;
12813 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12815 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12816 MonoReflectionFieldBuilder *fb;
12817 MonoClassField *field;
12818 MonoImage *image = klass->image;
12819 const char *p, *p2;
12821 guint32 len, idx, real_size = 0;
12823 klass->field.count = tb->num_fields;
12824 klass->field.first = 0;
12826 mono_error_init (error);
12828 if (tb->class_size) {
12829 if ((tb->packing_size & 0xffffff00) != 0) {
12830 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12831 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12834 klass->packing_size = tb->packing_size;
12835 real_size = klass->instance_size + tb->class_size;
12838 if (!klass->field.count) {
12839 klass->instance_size = MAX (klass->instance_size, real_size);
12843 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12844 mono_class_alloc_ext (klass);
12845 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12847 This is, guess what, a hack.
12848 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12849 On the static path no field class is resolved, only types are built. This is the right thing to do
12851 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12853 klass->size_inited = 1;
12855 for (i = 0; i < klass->field.count; ++i) {
12856 MonoArray *rva_data;
12857 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12858 field = &klass->fields [i];
12859 field->name = mono_string_to_utf8_image (image, fb->name, error);
12860 if (!mono_error_ok (error))
12863 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12864 return_if_nok (error);
12865 field->type = mono_metadata_type_dup (klass->image, type);
12866 field->type->attrs = fb->attrs;
12868 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12869 return_if_nok (error);
12872 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12873 char *base = mono_array_addr (rva_data, char, 0);
12874 size_t size = mono_array_length (rva_data);
12875 char *data = (char *)mono_image_alloc (klass->image, size);
12876 memcpy (data, base, size);
12877 klass->ext->field_def_values [i].data = data;
12879 if (fb->offset != -1)
12880 field->offset = fb->offset;
12881 field->parent = klass;
12882 fb->handle = field;
12883 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12885 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12886 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12888 if (fb->def_value) {
12889 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12890 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12891 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12892 /* Copy the data from the blob since it might get realloc-ed */
12893 p = assembly->blob.data + idx;
12894 len = mono_metadata_decode_blob_size (p, &p2);
12896 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12897 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12901 klass->instance_size = MAX (klass->instance_size, real_size);
12902 mono_class_layout_fields (klass, klass->instance_size);
12906 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12908 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12909 MonoReflectionPropertyBuilder *pb;
12910 MonoImage *image = klass->image;
12911 MonoProperty *properties;
12914 mono_error_init (error);
12917 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12919 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12920 klass->ext->property.first = 0;
12922 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12923 klass->ext->properties = properties;
12924 for (i = 0; i < klass->ext->property.count; ++i) {
12925 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12926 properties [i].parent = klass;
12927 properties [i].attrs = pb->attrs;
12928 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12929 if (!mono_error_ok (error))
12931 if (pb->get_method)
12932 properties [i].get = pb->get_method->mhandle;
12933 if (pb->set_method)
12934 properties [i].set = pb->set_method->mhandle;
12936 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12937 if (pb->def_value) {
12939 const char *p, *p2;
12940 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12941 if (!klass->ext->prop_def_values)
12942 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12943 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12944 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12945 /* Copy the data from the blob since it might get realloc-ed */
12946 p = assembly->blob.data + idx;
12947 len = mono_metadata_decode_blob_size (p, &p2);
12949 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12950 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12955 static MonoReflectionEvent *
12956 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12958 mono_error_init (error);
12960 MonoEvent *event = g_new0 (MonoEvent, 1);
12963 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12964 if (!is_ok (error)) {
12968 klass = mono_class_from_mono_type (type);
12970 event->parent = klass;
12971 event->attrs = eb->attrs;
12972 event->name = mono_string_to_utf8 (eb->name);
12973 if (eb->add_method)
12974 event->add = eb->add_method->mhandle;
12975 if (eb->remove_method)
12976 event->remove = eb->remove_method->mhandle;
12977 if (eb->raise_method)
12978 event->raise = eb->raise_method->mhandle;
12980 #ifndef MONO_SMALL_CONFIG
12981 if (eb->other_methods) {
12983 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12984 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12985 MonoReflectionMethodBuilder *mb =
12986 mono_array_get (eb->other_methods,
12987 MonoReflectionMethodBuilder*, j);
12988 event->other [j] = mb->mhandle;
12993 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12994 if (!is_ok (error)) {
12995 #ifndef MONO_SMALL_CONFIG
12996 g_free (event->other);
13004 MonoReflectionEvent *
13005 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13008 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13009 mono_error_set_pending_exception (&error);
13014 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13016 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13017 MonoReflectionEventBuilder *eb;
13018 MonoImage *image = klass->image;
13022 mono_error_init (error);
13025 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13027 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13028 klass->ext->event.first = 0;
13030 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13031 klass->ext->events = events;
13032 for (i = 0; i < klass->ext->event.count; ++i) {
13033 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13034 events [i].parent = klass;
13035 events [i].attrs = eb->attrs;
13036 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13037 if (!mono_error_ok (error))
13039 if (eb->add_method)
13040 events [i].add = eb->add_method->mhandle;
13041 if (eb->remove_method)
13042 events [i].remove = eb->remove_method->mhandle;
13043 if (eb->raise_method)
13044 events [i].raise = eb->raise_method->mhandle;
13046 #ifndef MONO_SMALL_CONFIG
13047 if (eb->other_methods) {
13049 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13050 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13051 MonoReflectionMethodBuilder *mb =
13052 mono_array_get (eb->other_methods,
13053 MonoReflectionMethodBuilder*, j);
13054 events [i].other [j] = mb->mhandle;
13058 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13062 struct remove_instantiations_user_data
13069 remove_instantiations_of_and_ensure_contents (gpointer key,
13071 gpointer user_data)
13073 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13074 MonoType *type = (MonoType*)key;
13075 MonoClass *klass = data->klass;
13076 gboolean already_failed = !is_ok (data->error);
13078 MonoError *error = already_failed ? &lerror : data->error;
13080 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13081 MonoClass *inst_klass = mono_class_from_mono_type (type);
13082 //Ensure it's safe to use it.
13083 if (!fix_partial_generic_class (inst_klass, error)) {
13084 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13085 // Marked the class with failure, but since some other instantiation already failed,
13086 // just report that one, and swallow the error from this one.
13087 if (already_failed)
13088 mono_error_cleanup (error);
13096 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13098 mono_error_init (error);
13104 for (i = 0; i < mono_array_length (arr); ++i) {
13105 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13106 if (!mono_error_ok (error))
13111 MonoReflectionType*
13112 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13116 MonoDomain* domain;
13117 MonoReflectionType* res;
13120 mono_error_init (&error);
13122 domain = mono_object_domain (tb);
13123 klass = mono_class_from_mono_type (tb->type.type);
13126 * Check for user defined Type subclasses.
13128 RESOLVE_TYPE (tb->parent, &error);
13129 if (!is_ok (&error))
13130 goto failure_unlocked;
13131 check_array_for_usertypes (tb->interfaces, &error);
13132 if (!is_ok (&error))
13133 goto failure_unlocked;
13135 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13136 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13138 RESOLVE_TYPE (fb->type, &error);
13139 if (!is_ok (&error))
13140 goto failure_unlocked;
13141 check_array_for_usertypes (fb->modreq, &error);
13142 if (!is_ok (&error))
13143 goto failure_unlocked;
13144 check_array_for_usertypes (fb->modopt, &error);
13145 if (!is_ok (&error))
13146 goto failure_unlocked;
13147 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13148 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13149 if (!is_ok (&error))
13150 goto failure_unlocked;
13156 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13157 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13159 RESOLVE_TYPE (mb->rtype, &error);
13160 if (!is_ok (&error))
13161 goto failure_unlocked;
13162 check_array_for_usertypes (mb->return_modreq, &error);
13163 if (!is_ok (&error))
13164 goto failure_unlocked;
13165 check_array_for_usertypes (mb->return_modopt, &error);
13166 if (!is_ok (&error))
13167 goto failure_unlocked;
13168 check_array_for_usertypes (mb->parameters, &error);
13169 if (!is_ok (&error))
13170 goto failure_unlocked;
13171 if (mb->param_modreq)
13172 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13173 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13174 if (!is_ok (&error))
13175 goto failure_unlocked;
13177 if (mb->param_modopt)
13178 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13179 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13180 if (!is_ok (&error))
13181 goto failure_unlocked;
13187 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13188 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13190 check_array_for_usertypes (mb->parameters, &error);
13191 if (!is_ok (&error))
13192 goto failure_unlocked;
13193 if (mb->param_modreq)
13194 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13195 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13196 if (!is_ok (&error))
13197 goto failure_unlocked;
13199 if (mb->param_modopt)
13200 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13201 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13202 if (!is_ok (&error))
13203 goto failure_unlocked;
13209 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13212 * we need to lock the domain because the lock will be taken inside
13213 * So, we need to keep the locking order correct.
13215 mono_loader_lock ();
13216 mono_domain_lock (domain);
13217 if (klass->wastypebuilder) {
13218 mono_domain_unlock (domain);
13219 mono_loader_unlock ();
13221 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13222 mono_error_set_pending_exception (&error);
13227 * Fields to set in klass:
13228 * the various flags: delegate/unicode/contextbound etc.
13230 klass->flags = tb->attrs;
13231 klass->has_cctor = 1;
13232 klass->has_finalize = 1;
13233 klass->has_finalize_inited = 1;
13235 mono_class_setup_parent (klass, klass->parent);
13236 /* fool mono_class_setup_supertypes */
13237 klass->supertypes = NULL;
13238 mono_class_setup_supertypes (klass);
13239 mono_class_setup_mono_type (klass);
13242 if (!((MonoDynamicImage*)klass->image)->run) {
13243 if (klass->generic_container) {
13244 /* FIXME: The code below can't handle generic classes */
13245 klass->wastypebuilder = TRUE;
13246 mono_loader_unlock ();
13247 mono_domain_unlock (domain);
13249 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13250 mono_error_set_pending_exception (&error);
13257 /* enums are done right away */
13258 if (!klass->enumtype)
13259 if (!ensure_runtime_vtable (klass, &error))
13262 if (tb->subtypes) {
13263 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13264 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13265 mono_class_alloc_ext (klass);
13266 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13267 if (!is_ok (&error)) goto failure;
13268 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13272 klass->nested_classes_inited = TRUE;
13274 /* fields and object layout */
13275 if (klass->parent) {
13276 if (!klass->parent->size_inited)
13277 mono_class_init (klass->parent);
13278 klass->instance_size = klass->parent->instance_size;
13279 klass->sizes.class_size = 0;
13280 klass->min_align = klass->parent->min_align;
13281 /* if the type has no fields we won't call the field_setup
13282 * routine which sets up klass->has_references.
13284 klass->has_references |= klass->parent->has_references;
13286 klass->instance_size = sizeof (MonoObject);
13287 klass->min_align = 1;
13290 /* FIXME: handle packing_size and instance_size */
13291 typebuilder_setup_fields (klass, &error);
13292 if (!mono_error_ok (&error))
13294 typebuilder_setup_properties (klass, &error);
13295 if (!mono_error_ok (&error))
13298 typebuilder_setup_events (klass, &error);
13299 if (!mono_error_ok (&error))
13302 klass->wastypebuilder = TRUE;
13305 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13306 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13307 * we want to return normal System.MonoType objects, so clear these out from the cache.
13309 * Together with this we must ensure the contents of all instances to match the created type.
13311 if (domain->type_hash && klass->generic_container) {
13312 struct remove_instantiations_user_data data;
13313 data.klass = klass;
13314 data.error = &error;
13315 mono_error_assert_ok (&error);
13316 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13317 if (!is_ok (&error))
13321 mono_domain_unlock (domain);
13322 mono_loader_unlock ();
13324 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13325 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13326 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13327 goto failure_unlocked;
13330 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13331 if (!is_ok (&error))
13332 goto failure_unlocked;
13334 g_assert (res != (MonoReflectionType*)tb);
13339 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13340 klass->wastypebuilder = TRUE;
13341 mono_domain_unlock (domain);
13342 mono_loader_unlock ();
13344 mono_error_set_pending_exception (&error);
13349 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13351 MonoGenericParamFull *param;
13355 mono_error_init (error);
13357 image = &gparam->tbuilder->module->dynamic_image->image;
13359 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13361 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13362 mono_error_assert_ok (error);
13363 param->param.num = gparam->index;
13365 if (gparam->mbuilder) {
13366 if (!gparam->mbuilder->generic_container) {
13367 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13368 return_val_if_nok (error, FALSE);
13370 MonoClass *klass = mono_class_from_mono_type (tb);
13371 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13372 gparam->mbuilder->generic_container->is_method = TRUE;
13374 * Cannot set owner.method, since the MonoMethod is not created yet.
13375 * Set the image field instead, so type_in_image () works.
13377 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13378 gparam->mbuilder->generic_container->owner.image = klass->image;
13380 param->param.owner = gparam->mbuilder->generic_container;
13381 } else if (gparam->tbuilder) {
13382 if (!gparam->tbuilder->generic_container) {
13383 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13384 return_val_if_nok (error, FALSE);
13385 MonoClass *klass = mono_class_from_mono_type (tb);
13386 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13387 gparam->tbuilder->generic_container->owner.klass = klass;
13389 param->param.owner = gparam->tbuilder->generic_container;
13392 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13394 gparam->type.type = &pklass->byval_arg;
13396 mono_class_set_ref_info (pklass, gparam);
13397 mono_image_append_class_to_reflection_info_set (pklass);
13403 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13406 (void) reflection_initialize_generic_parameter (gparam, &error);
13407 mono_error_set_pending_exception (&error);
13412 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13415 MonoReflectionModuleBuilder *module = sig->module;
13416 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13417 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13422 check_array_for_usertypes (sig->arguments, &error);
13423 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13425 sigbuffer_init (&buf, 32);
13427 sigbuffer_add_value (&buf, 0x07);
13428 sigbuffer_add_value (&buf, na);
13429 if (assembly != NULL){
13430 for (i = 0; i < na; ++i) {
13431 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13432 encode_reflection_type (assembly, type, &buf, &error);
13433 if (!is_ok (&error)) goto fail;
13437 buflen = buf.p - buf.buf;
13438 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13439 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13440 sigbuffer_free (&buf);
13443 sigbuffer_free (&buf);
13444 mono_error_raise_exception (&error); /* FIXME don't raise here */
13449 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13452 MonoDynamicImage *assembly = sig->module->dynamic_image;
13453 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13458 check_array_for_usertypes (sig->arguments, &error);
13459 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13461 sigbuffer_init (&buf, 32);
13463 sigbuffer_add_value (&buf, 0x06);
13464 for (i = 0; i < na; ++i) {
13465 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13466 encode_reflection_type (assembly, type, &buf, &error);
13467 if (!is_ok (&error))
13471 buflen = buf.p - buf.buf;
13472 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13473 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13474 sigbuffer_free (&buf);
13478 sigbuffer_free (&buf);
13479 mono_error_raise_exception (&error); /* FIXME don't raise here */
13484 MonoMethod *handle;
13485 MonoDomain *domain;
13486 } DynamicMethodReleaseData;
13489 * The runtime automatically clean up those after finalization.
13491 static MonoReferenceQueue *dynamic_method_queue;
13494 free_dynamic_method (void *dynamic_method)
13496 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13497 MonoDomain *domain = data->domain;
13498 MonoMethod *method = data->handle;
13501 mono_domain_lock (domain);
13502 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13503 g_hash_table_remove (domain->method_to_dyn_method, method);
13504 mono_domain_unlock (domain);
13505 g_assert (dis_link);
13506 mono_gchandle_free (dis_link);
13508 mono_runtime_free_method (domain, method);
13513 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13515 MonoReferenceQueue *queue;
13516 MonoMethod *handle;
13517 DynamicMethodReleaseData *release_data;
13518 ReflectionMethodBuilder rmb;
13519 MonoMethodSignature *sig;
13521 MonoDomain *domain;
13525 mono_error_init (error);
13527 if (mono_runtime_is_shutting_down ()) {
13528 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13532 if (!(queue = dynamic_method_queue)) {
13533 mono_loader_lock ();
13534 if (!(queue = dynamic_method_queue))
13535 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13536 mono_loader_unlock ();
13539 sig = dynamic_method_to_signature (mb, error);
13540 return_val_if_nok (error, FALSE);
13542 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13545 * Resolve references.
13548 * Every second entry in the refs array is reserved for storing handle_class,
13549 * which is needed by the ldtoken implementation in the JIT.
13551 rmb.nrefs = mb->nrefs;
13552 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13553 for (i = 0; i < mb->nrefs; i += 2) {
13554 MonoClass *handle_class;
13556 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13558 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13559 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13561 * The referenced DynamicMethod should already be created by the managed
13562 * code, except in the case of circular references. In that case, we store
13563 * method in the refs array, and fix it up later when the referenced
13564 * DynamicMethod is created.
13566 if (method->mhandle) {
13567 ref = method->mhandle;
13569 /* FIXME: GC object stored in unmanaged memory */
13572 /* FIXME: GC object stored in unmanaged memory */
13573 method->referenced_by = g_slist_append (method->referenced_by, mb);
13575 handle_class = mono_defaults.methodhandle_class;
13577 MonoException *ex = NULL;
13578 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13579 if (!is_ok (error)) {
13584 ex = mono_get_exception_type_load (NULL, NULL);
13585 else if (mono_security_core_clr_enabled ())
13586 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13590 mono_error_set_exception_instance (error, ex);
13595 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13596 rmb.refs [i + 1] = handle_class;
13600 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13601 if (!is_ok (error)) {
13605 klass = mono_class_from_mono_type (owner_type);
13607 klass = mono_defaults.object_class;
13610 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13611 release_data = g_new (DynamicMethodReleaseData, 1);
13612 release_data->handle = handle;
13613 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13614 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13615 g_free (release_data);
13617 /* Fix up refs entries pointing at us */
13618 for (l = mb->referenced_by; l; l = l->next) {
13619 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13620 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13623 g_assert (method->mhandle);
13625 data = (gpointer*)wrapper->method_data;
13626 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13627 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13628 data [i + 1] = mb->mhandle;
13631 g_slist_free (mb->referenced_by);
13635 /* ilgen is no longer needed */
13638 domain = mono_domain_get ();
13639 mono_domain_lock (domain);
13640 if (!domain->method_to_dyn_method)
13641 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13642 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13643 mono_domain_unlock (domain);
13649 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13652 (void) reflection_create_dynamic_method (mb, &error);
13653 mono_error_set_pending_exception (&error);
13656 #endif /* DISABLE_REFLECTION_EMIT */
13660 * mono_reflection_is_valid_dynamic_token:
13662 * Returns TRUE if token is valid.
13666 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13668 return lookup_dyn_token (image, token) != NULL;
13671 MonoMethodSignature *
13672 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13674 MonoMethodSignature *sig;
13675 g_assert (image_is_dynamic (image));
13677 mono_error_init (error);
13679 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13683 return mono_method_signature_checked (method, error);
13686 #ifndef DISABLE_REFLECTION_EMIT
13689 * mono_reflection_lookup_dynamic_token:
13691 * Finish the Builder object pointed to by TOKEN and return the corresponding
13692 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13693 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13696 * LOCKING: Take the loader lock
13699 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13701 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13705 mono_error_init (error);
13707 obj = lookup_dyn_token (assembly, token);
13710 g_error ("Could not find required dynamic token 0x%08x", token);
13712 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13718 handle_class = &klass;
13719 gpointer result = resolve_object (image, obj, handle_class, context, error);
13724 * ensure_complete_type:
13726 * Ensure that KLASS is completed if it is a dynamic type, or references
13730 ensure_complete_type (MonoClass *klass, MonoError *error)
13732 mono_error_init (error);
13734 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13735 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13737 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13738 return_if_nok (error);
13740 // Asserting here could break a lot of code
13741 //g_assert (klass->wastypebuilder);
13744 if (klass->generic_class) {
13745 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13748 for (i = 0; i < inst->type_argc; ++i) {
13749 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13750 return_if_nok (error);
13756 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13758 gpointer result = NULL;
13760 mono_error_init (error);
13762 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13763 result = mono_string_intern_checked ((MonoString*)obj, error);
13764 return_val_if_nok (error, NULL);
13765 *handle_class = mono_defaults.string_class;
13767 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13768 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13769 return_val_if_nok (error, NULL);
13770 MonoClass *mc = mono_class_from_mono_type (type);
13771 if (!mono_class_init (mc)) {
13772 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13777 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13778 return_val_if_nok (error, NULL);
13780 result = mono_class_from_mono_type (inflated);
13781 mono_metadata_free_type (inflated);
13783 result = mono_class_from_mono_type (type);
13785 *handle_class = mono_defaults.typehandle_class;
13787 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13788 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13789 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13790 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13791 result = ((MonoReflectionMethod*)obj)->method;
13793 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13794 mono_error_assert_ok (error);
13796 *handle_class = mono_defaults.methodhandle_class;
13798 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13799 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13800 result = mb->mhandle;
13802 /* Type is not yet created */
13803 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13805 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13806 return_val_if_nok (error, NULL);
13809 * Hopefully this has been filled in by calling CreateType() on the
13813 * TODO: This won't work if the application finishes another
13814 * TypeBuilder instance instead of this one.
13816 result = mb->mhandle;
13819 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13820 mono_error_assert_ok (error);
13822 *handle_class = mono_defaults.methodhandle_class;
13823 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13824 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13826 result = cb->mhandle;
13828 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13830 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13831 return_val_if_nok (error, NULL);
13832 result = cb->mhandle;
13835 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13836 mono_error_assert_ok (error);
13838 *handle_class = mono_defaults.methodhandle_class;
13839 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13840 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13842 ensure_complete_type (field->parent, error);
13843 return_val_if_nok (error, NULL);
13846 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13847 return_val_if_nok (error, NULL);
13849 MonoClass *klass = mono_class_from_mono_type (inflated);
13850 MonoClassField *inflated_field;
13851 gpointer iter = NULL;
13852 mono_metadata_free_type (inflated);
13853 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13854 if (!strcmp (field->name, inflated_field->name))
13857 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13858 result = inflated_field;
13862 *handle_class = mono_defaults.fieldhandle_class;
13864 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13865 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13866 result = fb->handle;
13869 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13871 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13872 return_val_if_nok (error, NULL);
13873 result = fb->handle;
13876 if (fb->handle && fb->handle->parent->generic_container) {
13877 MonoClass *klass = fb->handle->parent;
13878 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13879 return_val_if_nok (error, NULL);
13881 MonoClass *inflated = mono_class_from_mono_type (type);
13883 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13885 mono_metadata_free_type (type);
13887 *handle_class = mono_defaults.fieldhandle_class;
13888 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13889 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13890 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13891 return_val_if_nok (error, NULL);
13894 klass = type->data.klass;
13895 if (klass->wastypebuilder) {
13896 /* Already created */
13900 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13901 return_val_if_nok (error, NULL);
13902 result = type->data.klass;
13905 *handle_class = mono_defaults.typehandle_class;
13906 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13907 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13908 MonoMethodSignature *sig;
13911 if (helper->arguments)
13912 nargs = mono_array_length (helper->arguments);
13916 sig = mono_metadata_signature_alloc (image, nargs);
13917 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13918 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13920 if (helper->unmanaged_call_conv) { /* unmanaged */
13921 sig->call_convention = helper->unmanaged_call_conv - 1;
13922 sig->pinvoke = TRUE;
13923 } else if (helper->call_conv & 0x02) {
13924 sig->call_convention = MONO_CALL_VARARG;
13926 sig->call_convention = MONO_CALL_DEFAULT;
13929 sig->param_count = nargs;
13930 /* TODO: Copy type ? */
13931 sig->ret = helper->return_type->type;
13932 for (i = 0; i < nargs; ++i) {
13933 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13934 if (!is_ok (error)) {
13935 image_g_free (image, sig);
13941 *handle_class = NULL;
13942 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13943 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13944 /* Already created by the managed code */
13945 g_assert (method->mhandle);
13946 result = method->mhandle;
13947 *handle_class = mono_defaults.methodhandle_class;
13948 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13949 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13950 return_val_if_nok (error, NULL);
13951 type = mono_class_inflate_generic_type_checked (type, context, error);
13952 return_val_if_nok (error, NULL);
13954 result = mono_class_from_mono_type (type);
13955 *handle_class = mono_defaults.typehandle_class;
13957 mono_metadata_free_type (type);
13958 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13959 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13960 return_val_if_nok (error, NULL);
13961 type = mono_class_inflate_generic_type_checked (type, context, error);
13962 return_val_if_nok (error, NULL);
13964 result = mono_class_from_mono_type (type);
13965 *handle_class = mono_defaults.typehandle_class;
13967 mono_metadata_free_type (type);
13968 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13969 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13970 MonoClass *inflated;
13972 MonoClassField *field;
13974 if (is_sre_field_builder (mono_object_class (f->fb)))
13975 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13976 else if (is_sr_mono_field (mono_object_class (f->fb)))
13977 field = ((MonoReflectionField*)f->fb)->field;
13979 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)));
13981 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13982 return_val_if_nok (error, NULL);
13983 type = mono_class_inflate_generic_type_checked (finst, context, error);
13984 return_val_if_nok (error, NULL);
13986 inflated = mono_class_from_mono_type (type);
13988 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13989 ensure_complete_type (field->parent, error);
13990 if (!is_ok (error)) {
13991 mono_metadata_free_type (type);
13996 mono_metadata_free_type (type);
13997 *handle_class = mono_defaults.fieldhandle_class;
13998 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13999 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14000 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14001 return_val_if_nok (error, NULL);
14002 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14003 return_val_if_nok (error, NULL);
14005 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14006 MonoMethod *method;
14008 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14009 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14010 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14011 method = ((MonoReflectionMethod *)c->cb)->method;
14013 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)));
14015 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14016 *handle_class = mono_defaults.methodhandle_class;
14017 mono_metadata_free_type (type);
14018 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14019 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14020 if (m->method_args) {
14021 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14022 return_val_if_nok (error, NULL);
14024 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14025 mono_error_assert_ok (error);
14028 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14029 return_val_if_nok (error, NULL);
14030 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14031 return_val_if_nok (error, NULL);
14033 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14034 MonoMethod *method;
14036 if (is_sre_method_builder (mono_object_class (m->mb)))
14037 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14038 else if (is_sr_mono_method (mono_object_class (m->mb)))
14039 method = ((MonoReflectionMethod *)m->mb)->method;
14041 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)));
14043 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14044 mono_metadata_free_type (type);
14046 *handle_class = mono_defaults.methodhandle_class;
14047 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14048 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14051 MonoMethod *method;
14055 mtype = mono_reflection_type_get_handle (m->parent, error);
14056 return_val_if_nok (error, NULL);
14057 klass = mono_class_from_mono_type (mtype);
14059 /* Find the method */
14061 name = mono_string_to_utf8 (m->name);
14063 while ((method = mono_class_get_methods (klass, &iter))) {
14064 if (!strcmp (method->name, name))
14071 // FIXME: Check parameters/return value etc. match
14074 *handle_class = mono_defaults.methodhandle_class;
14075 } else if (is_sre_array (mono_object_get_class(obj)) ||
14076 is_sre_byref (mono_object_get_class(obj)) ||
14077 is_sre_pointer (mono_object_get_class(obj))) {
14078 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14079 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14080 return_val_if_nok (error, NULL);
14083 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14084 return_val_if_nok (error, NULL);
14086 result = mono_class_from_mono_type (inflated);
14087 mono_metadata_free_type (inflated);
14089 result = mono_class_from_mono_type (type);
14091 *handle_class = mono_defaults.typehandle_class;
14093 g_print ("%s\n", obj->vtable->klass->name);
14094 g_assert_not_reached ();
14099 #else /* DISABLE_REFLECTION_EMIT */
14102 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14104 g_assert_not_reached ();
14109 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14111 g_assert_not_reached ();
14115 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14117 g_assert_not_reached ();
14121 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14123 g_assert_not_reached ();
14127 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14129 g_assert_not_reached ();
14133 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14135 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14139 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14141 g_assert_not_reached ();
14145 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14147 g_assert_not_reached ();
14150 MonoReflectionModule *
14151 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14153 g_assert_not_reached ();
14158 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14160 g_assert_not_reached ();
14165 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14167 g_assert_not_reached ();
14172 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14173 gboolean create_open_instance, gboolean register_token, MonoError *error)
14175 g_assert_not_reached ();
14180 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14185 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14187 g_assert_not_reached ();
14191 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14193 mono_error_init (error);
14195 *num_overrides = 0;
14198 MonoReflectionEvent *
14199 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14201 g_assert_not_reached ();
14205 MonoReflectionType*
14206 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14208 g_assert_not_reached ();
14213 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14215 g_assert_not_reached ();
14219 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14221 g_assert_not_reached ();
14226 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14228 g_assert_not_reached ();
14233 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14238 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14244 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14246 mono_error_init (error);
14253 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14255 g_assert_not_reached ();
14258 #endif /* DISABLE_REFLECTION_EMIT */
14260 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14261 const static guint32 declsec_flags_map[] = {
14262 0x00000000, /* empty */
14263 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14264 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14265 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14266 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14267 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14268 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14269 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14270 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14271 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14272 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14273 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14274 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14275 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14276 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14277 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14278 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14279 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14280 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14284 * Returns flags that includes all available security action associated to the handle.
14285 * @token: metadata token (either for a class or a method)
14286 * @image: image where resides the metadata.
14289 mono_declsec_get_flags (MonoImage *image, guint32 token)
14291 int index = mono_metadata_declsec_from_index (image, token);
14292 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14293 guint32 result = 0;
14297 /* HasSecurity can be present for other, not specially encoded, attributes,
14298 e.g. SuppressUnmanagedCodeSecurityAttribute */
14302 for (i = index; i < t->rows; i++) {
14303 guint32 cols [MONO_DECL_SECURITY_SIZE];
14305 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14306 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14309 action = cols [MONO_DECL_SECURITY_ACTION];
14310 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14311 result |= declsec_flags_map [action];
14313 g_assert_not_reached ();
14320 * Get the security actions (in the form of flags) associated with the specified method.
14322 * @method: The method for which we want the declarative security flags.
14323 * Return the declarative security flags for the method (only).
14325 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14326 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14329 mono_declsec_flags_from_method (MonoMethod *method)
14331 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14332 /* FIXME: No cache (for the moment) */
14333 guint32 idx = mono_method_get_index (method);
14334 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14335 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14336 return mono_declsec_get_flags (method->klass->image, idx);
14342 * Get the security actions (in the form of flags) associated with the specified class.
14344 * @klass: The class for which we want the declarative security flags.
14345 * Return the declarative security flags for the class.
14347 * Note: We cache the flags inside the MonoClass structure as this will get
14348 * called very often (at least for each method).
14351 mono_declsec_flags_from_class (MonoClass *klass)
14353 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14354 if (!klass->ext || !klass->ext->declsec_flags) {
14357 idx = mono_metadata_token_index (klass->type_token);
14358 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14359 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14360 mono_loader_lock ();
14361 mono_class_alloc_ext (klass);
14362 mono_loader_unlock ();
14363 /* we cache the flags on classes */
14364 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14366 return klass->ext->declsec_flags;
14372 * Get the security actions (in the form of flags) associated with the specified assembly.
14374 * @assembly: The assembly for which we want the declarative security flags.
14375 * Return the declarative security flags for the assembly.
14378 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14380 guint32 idx = 1; /* there is only one assembly */
14381 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14382 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14383 return mono_declsec_get_flags (assembly->image, idx);
14388 * Fill actions for the specific index (which may either be an encoded class token or
14389 * an encoded method token) from the metadata image.
14390 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14393 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14394 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14396 MonoBoolean result = FALSE;
14398 guint32 cols [MONO_DECL_SECURITY_SIZE];
14399 int index = mono_metadata_declsec_from_index (image, token);
14402 t = &image->tables [MONO_TABLE_DECLSECURITY];
14403 for (i = index; i < t->rows; i++) {
14404 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14406 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14409 /* if present only replace (class) permissions with method permissions */
14410 /* if empty accept either class or method permissions */
14411 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14412 if (!actions->demand.blob) {
14413 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14414 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14415 actions->demand.blob = (char*) (blob + 2);
14416 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14419 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14420 if (!actions->noncasdemand.blob) {
14421 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14422 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14423 actions->noncasdemand.blob = (char*) (blob + 2);
14424 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14427 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14428 if (!actions->demandchoice.blob) {
14429 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14430 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14431 actions->demandchoice.blob = (char*) (blob + 2);
14432 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14442 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14443 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14445 guint32 idx = mono_metadata_token_index (klass->type_token);
14446 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14447 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14448 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14452 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14453 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14455 guint32 idx = mono_method_get_index (method);
14456 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14457 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14458 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14462 * Collect all actions (that requires to generate code in mini) assigned for
14463 * the specified method.
14464 * Note: Don't use the content of actions if the function return FALSE.
14467 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14469 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14470 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14471 MonoBoolean result = FALSE;
14474 /* quick exit if no declarative security is present in the metadata */
14475 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14478 /* we want the original as the wrapper is "free" of the security informations */
14479 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14480 method = mono_marshal_method_from_wrapper (method);
14485 /* First we look for method-level attributes */
14486 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14487 mono_class_init (method->klass);
14488 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14490 result = mono_declsec_get_method_demands_params (method, demands,
14491 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14494 /* Here we use (or create) the class declarative cache to look for demands */
14495 flags = mono_declsec_flags_from_class (method->klass);
14496 if (flags & mask) {
14498 mono_class_init (method->klass);
14499 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14501 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14502 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14505 /* The boolean return value is used as a shortcut in case nothing needs to
14506 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14512 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14514 * Note: Don't use the content of actions if the function return FALSE.
14517 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14519 MonoBoolean result = FALSE;
14522 /* quick exit if no declarative security is present in the metadata */
14523 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14526 /* we want the original as the wrapper is "free" of the security informations */
14527 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14528 method = mono_marshal_method_from_wrapper (method);
14533 /* results are independant - zeroize both */
14534 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14535 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14537 /* First we look for method-level attributes */
14538 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14539 mono_class_init (method->klass);
14541 result = mono_declsec_get_method_demands_params (method, cmethod,
14542 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14545 /* Here we use (or create) the class declarative cache to look for demands */
14546 flags = mono_declsec_flags_from_class (method->klass);
14547 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14548 mono_class_init (method->klass);
14550 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14551 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14558 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14560 * @klass The inherited class - this is the class that provides the security check (attributes)
14562 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14564 * Note: Don't use the content of actions if the function return FALSE.
14567 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14569 MonoBoolean result = FALSE;
14572 /* quick exit if no declarative security is present in the metadata */
14573 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14576 /* Here we use (or create) the class declarative cache to look for demands */
14577 flags = mono_declsec_flags_from_class (klass);
14578 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14579 mono_class_init (klass);
14580 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14582 result |= mono_declsec_get_class_demands_params (klass, demands,
14583 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14590 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14592 * Note: Don't use the content of actions if the function return FALSE.
14595 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14597 /* quick exit if no declarative security is present in the metadata */
14598 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14601 /* we want the original as the wrapper is "free" of the security informations */
14602 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14603 method = mono_marshal_method_from_wrapper (method);
14608 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14609 mono_class_init (method->klass);
14610 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14612 return mono_declsec_get_method_demands_params (method, demands,
14613 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14620 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14622 guint32 cols [MONO_DECL_SECURITY_SIZE];
14626 int index = mono_metadata_declsec_from_index (image, token);
14630 t = &image->tables [MONO_TABLE_DECLSECURITY];
14631 for (i = index; i < t->rows; i++) {
14632 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14634 /* shortcut - index are ordered */
14635 if (token != cols [MONO_DECL_SECURITY_PARENT])
14638 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14639 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14640 entry->blob = (char*) (metadata + 2);
14641 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14650 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14652 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14653 guint32 idx = mono_method_get_index (method);
14654 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14655 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14656 return get_declsec_action (method->klass->image, idx, action, entry);
14662 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14665 guint32 flags = mono_declsec_flags_from_class (klass);
14666 if (declsec_flags_map [action] & flags) {
14667 guint32 idx = mono_metadata_token_index (klass->type_token);
14668 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14669 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14670 return get_declsec_action (klass->image, idx, action, entry);
14676 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14678 guint32 idx = 1; /* there is only one assembly */
14679 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14680 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14682 return get_declsec_action (assembly->image, idx, action, entry);
14686 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14688 MonoObject *res, *exc;
14690 static MonoMethod *method = NULL;
14692 mono_error_init (error);
14694 if (method == NULL) {
14695 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14700 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14701 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14703 g_assert (mono_class_get_ref_info (klass));
14704 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14706 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14707 return_val_if_nok (error, FALSE);
14709 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14711 if (exc || !mono_error_ok (error)) {
14712 mono_error_cleanup (error);
14715 return *(MonoBoolean*)mono_object_unbox (res);
14719 * mono_reflection_type_get_type:
14720 * @reftype: the System.Type object
14722 * Returns the MonoType* associated with the C# System.Type object @reftype.
14725 mono_reflection_type_get_type (MonoReflectionType *reftype)
14727 g_assert (reftype);
14730 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14731 mono_error_assert_ok (&error);
14736 * mono_reflection_assembly_get_assembly:
14737 * @refassembly: the System.Reflection.Assembly object
14739 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14742 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14744 g_assert (refassembly);
14746 return refassembly->assembly;