2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/mempool-internals.h>
41 #include <mono/metadata/security-core-clr.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-ptr-array.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/checked-build.h>
49 static gboolean is_usertype (MonoReflectionType *ref);
50 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA 0x00002000
65 MonoReflectionILGen *ilgen;
66 MonoReflectionType *rtype;
67 MonoArray *parameters;
68 MonoArray *generic_params;
69 MonoGenericContainer *generic_container;
75 guint32 *table_idx; /* note: it's a pointer */
79 MonoBoolean init_locals;
80 MonoBoolean skip_visibility;
81 MonoArray *return_modreq;
82 MonoArray *return_modopt;
83 MonoArray *param_modreq;
84 MonoArray *param_modopt;
85 MonoArray *permissions;
90 int charset, extra_flags, native_cc;
91 MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
96 MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
109 MONO_INTERFACEIMPL_SIZE,
110 MONO_MEMBERREF_SIZE, /* 0x0A */
112 MONO_CUSTOM_ATTR_SIZE,
113 MONO_FIELD_MARSHAL_SIZE,
114 MONO_DECL_SECURITY_SIZE,
115 MONO_CLASS_LAYOUT_SIZE,
116 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117 MONO_STAND_ALONE_SIGNATURE_SIZE,
121 MONO_PROPERTY_MAP_SIZE,
124 MONO_METHOD_SEMA_SIZE,
125 MONO_METHODIMPL_SIZE,
126 MONO_MODULEREF_SIZE, /* 0x1A */
132 MONO_ASSEMBLY_SIZE, /* 0x20 */
133 MONO_ASSEMBLY_PROCESSOR_SIZE,
134 MONO_ASSEMBLYOS_SIZE,
135 MONO_ASSEMBLYREF_SIZE,
136 MONO_ASSEMBLYREFPROC_SIZE,
137 MONO_ASSEMBLYREFOS_SIZE,
141 MONO_NESTED_CLASS_SIZE,
143 MONO_GENERICPARAM_SIZE, /* 0x2A */
144 MONO_METHODSPEC_SIZE,
145 MONO_GENPARCONSTRAINT_SIZE
149 #ifndef DISABLE_REFLECTION_EMIT
150 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
151 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
152 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
153 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
154 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
155 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
157 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
158 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
159 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
160 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
161 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
167 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
168 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
169 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
170 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
171 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
172 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
173 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
174 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
175 static gboolean is_sre_array (MonoClass *klass);
176 static gboolean is_sre_byref (MonoClass *klass);
177 static gboolean is_sre_pointer (MonoClass *klass);
178 static gboolean is_sre_type_builder (MonoClass *klass);
179 static gboolean is_sre_method_builder (MonoClass *klass);
180 static gboolean is_sre_ctor_builder (MonoClass *klass);
181 static gboolean is_sre_field_builder (MonoClass *klass);
182 static gboolean is_sr_mono_method (MonoClass *klass);
183 static gboolean is_sr_mono_cmethod (MonoClass *klass);
184 static gboolean is_sr_mono_generic_method (MonoClass *klass);
185 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
186 static gboolean is_sr_mono_field (MonoClass *klass);
187 static gboolean is_sr_mono_property (MonoClass *klass);
188 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
189 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
191 static gboolean type_is_reference (MonoType *type);
193 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
194 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
195 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
197 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
198 static void init_type_builder_generics (MonoObject *type, MonoError *error);
200 #define RESOLVE_TYPE(type, error) do { \
201 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
204 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205 __type = mono_reflection_type_resolve_user_types (__type, error); \
206 if (mono_error_ok (error)) \
207 mono_array_set (arr, MonoReflectionType*, index, __type); \
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
250 dynamic_images_lock (void)
252 mono_os_mutex_lock (&dynamic_images_mutex);
256 dynamic_images_unlock (void)
258 mono_os_mutex_unlock (&dynamic_images_mutex);
262 * mono_find_dynamic_image_owner:
264 * Find the dynamic image, if any, which a given pointer is located in the memory of.
267 mono_find_dynamic_image_owner (void *ptr)
269 MonoImage *owner = NULL;
272 dynamic_images_lock ();
276 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278 if (mono_mempool_contains_addr (image->mempool, ptr))
283 dynamic_images_unlock ();
289 mono_reflection_init (void)
291 mono_os_mutex_init (&dynamic_images_mutex);
295 dynamic_image_lock (MonoDynamicImage *image)
298 mono_image_lock ((MonoImage*)image);
303 dynamic_image_unlock (MonoDynamicImage *image)
305 mono_image_unlock ((MonoImage*)image);
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
311 MONO_REQ_GC_UNSAFE_MODE;
313 dynamic_image_lock (assembly);
314 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315 dynamic_image_unlock (assembly);
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
321 MONO_REQ_GC_UNSAFE_MODE;
325 dynamic_image_lock (assembly);
326 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327 dynamic_image_unlock (assembly);
333 sigbuffer_init (SigBuffer *buf, int size)
335 MONO_REQ_GC_NEUTRAL_MODE;
337 buf->buf = (char *)g_malloc (size);
339 buf->end = buf->buf + size;
343 sigbuffer_make_room (SigBuffer *buf, int size)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 if (buf->end - buf->p < size) {
348 int new_size = buf->end - buf->buf + size + 32;
349 char *p = (char *)g_realloc (buf->buf, new_size);
350 size = buf->p - buf->buf;
353 buf->end = buf->buf + new_size;
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
360 MONO_REQ_GC_NEUTRAL_MODE;
362 sigbuffer_make_room (buf, 6);
363 mono_metadata_encode_value (val, buf->p, &buf->p);
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
369 MONO_REQ_GC_NEUTRAL_MODE;
371 sigbuffer_make_room (buf, 1);
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
379 MONO_REQ_GC_NEUTRAL_MODE;
381 sigbuffer_make_room (buf, size);
382 memcpy (buf->p, p, size);
387 sigbuffer_free (SigBuffer *buf)
389 MONO_REQ_GC_NEUTRAL_MODE;
394 #ifndef DISABLE_REFLECTION_EMIT
398 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
402 image_g_malloc (MonoImage *image, guint size)
404 MONO_REQ_GC_NEUTRAL_MODE;
407 return mono_image_alloc (image, size);
409 return g_malloc (size);
411 #endif /* !DISABLE_REFLECTION_EMIT */
416 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
420 image_g_malloc0 (MonoImage *image, guint size)
422 MONO_REQ_GC_NEUTRAL_MODE;
425 return mono_image_alloc0 (image, size);
427 return g_malloc0 (size);
432 * @image: a MonoImage
435 * If @image is NULL, free @ptr, otherwise do nothing.
438 image_g_free (MonoImage *image, gpointer ptr)
444 #ifndef DISABLE_REFLECTION_EMIT
446 image_strdup (MonoImage *image, const char *s)
448 MONO_REQ_GC_NEUTRAL_MODE;
451 return mono_image_strdup (image, s);
457 #define image_g_new(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
460 #define image_g_new0(image,struct_type, n_structs) \
461 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
465 alloc_table (MonoDynamicTable *table, guint nrows)
467 MONO_REQ_GC_NEUTRAL_MODE;
470 g_assert (table->columns);
471 if (nrows + 1 >= table->alloc_rows) {
472 while (nrows + 1 >= table->alloc_rows) {
473 if (table->alloc_rows == 0)
474 table->alloc_rows = 16;
476 table->alloc_rows *= 2;
479 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
484 make_room_in_stream (MonoDynamicStream *stream, int size)
486 MONO_REQ_GC_NEUTRAL_MODE;
488 if (size <= stream->alloc_size)
491 while (stream->alloc_size <= size) {
492 if (stream->alloc_size < 4096)
493 stream->alloc_size = 4096;
495 stream->alloc_size *= 2;
498 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
504 MONO_REQ_GC_NEUTRAL_MODE;
508 gpointer oldkey, oldval;
510 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511 return GPOINTER_TO_UINT (oldval);
513 len = strlen (str) + 1;
516 make_room_in_stream (sh, idx + len);
519 * We strdup the string even if we already copy them in sh->data
520 * so that the string pointers in the hash remain valid even if
521 * we need to realloc sh->data. We may want to avoid that later.
523 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524 memcpy (sh->data + idx, str, len);
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
532 MONO_REQ_GC_UNSAFE_MODE;
534 char *name = mono_string_to_utf8 (str);
536 idx = string_heap_insert (sh, name);
541 #ifndef DISABLE_REFLECTION_EMIT
543 string_heap_init (MonoDynamicStream *sh)
545 MONO_REQ_GC_NEUTRAL_MODE;
548 sh->alloc_size = 4096;
549 sh->data = (char *)g_malloc (4096);
550 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
551 string_heap_insert (sh, "");
556 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
558 MONO_REQ_GC_NEUTRAL_MODE;
562 make_room_in_stream (stream, stream->index + len);
563 memcpy (stream->data + stream->index, data, len);
565 stream->index += len;
567 * align index? Not without adding an additional param that controls it since
568 * we may store a blob value in pieces.
574 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
576 MONO_REQ_GC_NEUTRAL_MODE;
580 make_room_in_stream (stream, stream->index + len);
581 memset (stream->data + stream->index, 0, len);
583 stream->index += len;
588 stream_data_align (MonoDynamicStream *stream)
590 MONO_REQ_GC_NEUTRAL_MODE;
593 guint32 count = stream->index % 4;
595 /* we assume the stream data will be aligned */
597 mono_image_add_stream_data (stream, buf, 4 - count);
600 #ifndef DISABLE_REFLECTION_EMIT
602 mono_blob_entry_hash (const char* str)
604 MONO_REQ_GC_NEUTRAL_MODE;
608 len = mono_metadata_decode_blob_size (str, &str);
612 for (str += 1; str < end; str++)
613 h = (h << 5) - h + *str;
621 mono_blob_entry_equal (const char *str1, const char *str2) {
622 MONO_REQ_GC_NEUTRAL_MODE;
627 len = mono_metadata_decode_blob_size (str1, &end1);
628 len2 = mono_metadata_decode_blob_size (str2, &end2);
631 return memcmp (end1, end2, len) == 0;
635 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
637 MONO_REQ_GC_NEUTRAL_MODE;
641 gpointer oldkey, oldval;
643 copy = (char *)g_malloc (s1+s2);
644 memcpy (copy, b1, s1);
645 memcpy (copy + s1, b2, s2);
646 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
648 idx = GPOINTER_TO_UINT (oldval);
650 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
651 mono_image_add_stream_data (&assembly->blob, b2, s2);
652 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
658 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
660 MONO_REQ_GC_NEUTRAL_MODE;
664 guint32 size = buf->p - buf->buf;
666 g_assert (size <= (buf->end - buf->buf));
667 mono_metadata_encode_value (size, b, &b);
668 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
672 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
673 * dest may be misaligned.
676 swap_with_size (char *dest, const char* val, int len, int nelem) {
677 MONO_REQ_GC_NEUTRAL_MODE;
678 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
681 for (elem = 0; elem < nelem; ++elem) {
707 g_assert_not_reached ();
713 memcpy (dest, val, len * nelem);
718 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
720 MONO_REQ_GC_UNSAFE_MODE;
724 guint32 idx = 0, len;
726 len = str->length * 2;
727 mono_metadata_encode_value (len, b, &b);
728 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
730 char *swapped = g_malloc (2 * mono_string_length (str));
731 const char *p = (const char*)mono_string_chars (str);
733 swap_with_size (swapped, p, 2, mono_string_length (str));
734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
743 #ifndef DISABLE_REFLECTION_EMIT
745 default_class_from_mono_type (MonoType *type)
747 MONO_REQ_GC_NEUTRAL_MODE;
749 switch (type->type) {
750 case MONO_TYPE_OBJECT:
751 return mono_defaults.object_class;
753 return mono_defaults.void_class;
754 case MONO_TYPE_BOOLEAN:
755 return mono_defaults.boolean_class;
757 return mono_defaults.char_class;
759 return mono_defaults.sbyte_class;
761 return mono_defaults.byte_class;
763 return mono_defaults.int16_class;
765 return mono_defaults.uint16_class;
767 return mono_defaults.int32_class;
769 return mono_defaults.uint32_class;
771 return mono_defaults.int_class;
773 return mono_defaults.uint_class;
775 return mono_defaults.int64_class;
777 return mono_defaults.uint64_class;
779 return mono_defaults.single_class;
781 return mono_defaults.double_class;
782 case MONO_TYPE_STRING:
783 return mono_defaults.string_class;
785 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
786 g_assert_not_reached ();
794 * mono_class_get_ref_info:
796 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
799 mono_class_get_ref_info (MonoClass *klass)
801 MONO_REQ_GC_UNSAFE_MODE;
803 if (klass->ref_info_handle == 0)
806 return mono_gchandle_get_target (klass->ref_info_handle);
810 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
812 MONO_REQ_GC_UNSAFE_MODE;
814 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
815 g_assert (klass->ref_info_handle != 0);
819 mono_class_free_ref_info (MonoClass *klass)
821 MONO_REQ_GC_NEUTRAL_MODE;
823 if (klass->ref_info_handle) {
824 mono_gchandle_free (klass->ref_info_handle);
825 klass->ref_info_handle = 0;
830 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
832 MONO_REQ_GC_NEUTRAL_MODE;
835 MonoGenericInst *class_inst;
840 class_inst = gclass->context.class_inst;
842 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
843 klass = gclass->container_class;
844 sigbuffer_add_value (buf, klass->byval_arg.type);
845 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
847 sigbuffer_add_value (buf, class_inst->type_argc);
848 for (i = 0; i < class_inst->type_argc; ++i)
849 encode_type (assembly, class_inst->type_argv [i], buf);
854 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
856 MONO_REQ_GC_NEUTRAL_MODE;
859 g_assert_not_reached ();
864 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
868 case MONO_TYPE_BOOLEAN:
882 case MONO_TYPE_STRING:
883 case MONO_TYPE_OBJECT:
884 case MONO_TYPE_TYPEDBYREF:
885 sigbuffer_add_value (buf, type->type);
888 sigbuffer_add_value (buf, type->type);
889 encode_type (assembly, type->data.type, buf);
891 case MONO_TYPE_SZARRAY:
892 sigbuffer_add_value (buf, type->type);
893 encode_type (assembly, &type->data.klass->byval_arg, buf);
895 case MONO_TYPE_VALUETYPE:
896 case MONO_TYPE_CLASS: {
897 MonoClass *k = mono_class_from_mono_type (type);
899 if (k->generic_container) {
900 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
901 encode_generic_class (assembly, gclass, buf);
904 * Make sure we use the correct type.
906 sigbuffer_add_value (buf, k->byval_arg.type);
908 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
909 * otherwise two typerefs could point to the same type, leading to
910 * verification errors.
912 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
916 case MONO_TYPE_ARRAY:
917 sigbuffer_add_value (buf, type->type);
918 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
919 sigbuffer_add_value (buf, type->data.array->rank);
920 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
921 sigbuffer_add_value (buf, 0);
923 case MONO_TYPE_GENERICINST:
924 encode_generic_class (assembly, type->data.generic_class, buf);
928 sigbuffer_add_value (buf, type->type);
929 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
932 g_error ("need to encode type %x", type->type);
937 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
939 MONO_REQ_GC_UNSAFE_MODE;
941 mono_error_init (error);
944 sigbuffer_add_value (buf, MONO_TYPE_VOID);
948 MonoType *t = mono_reflection_type_get_handle (type, error);
949 return_if_nok (error);
950 encode_type (assembly, t, buf);
954 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
956 MONO_REQ_GC_UNSAFE_MODE;
960 mono_error_init (error);
963 for (i = 0; i < mono_array_length (modreq); ++i) {
964 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
965 return_if_nok (error);
966 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
967 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
971 for (i = 0; i < mono_array_length (modopt); ++i) {
972 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
973 return_if_nok (error);
974 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
975 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
980 #ifndef DISABLE_REFLECTION_EMIT
982 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
984 MONO_REQ_GC_UNSAFE_MODE;
988 guint32 nparams = sig->param_count;
994 sigbuffer_init (&buf, 32);
996 * FIXME: vararg, explicit_this, differenc call_conv values...
998 idx = sig->call_convention;
1000 idx |= 0x20; /* hasthis */
1001 if (sig->generic_param_count)
1002 idx |= 0x10; /* generic */
1003 sigbuffer_add_byte (&buf, idx);
1004 if (sig->generic_param_count)
1005 sigbuffer_add_value (&buf, sig->generic_param_count);
1006 sigbuffer_add_value (&buf, nparams);
1007 encode_type (assembly, sig->ret, &buf);
1008 for (i = 0; i < nparams; ++i) {
1009 if (i == sig->sentinelpos)
1010 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1011 encode_type (assembly, sig->params [i], &buf);
1013 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1014 sigbuffer_free (&buf);
1020 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1022 MONO_REQ_GC_UNSAFE_MODE;
1024 mono_error_init (error);
1027 * FIXME: reuse code from method_encode_signature().
1031 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1032 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1033 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1036 sigbuffer_init (&buf, 32);
1037 /* LAMESPEC: all the call conv spec is foobared */
1038 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1039 if (mb->call_conv & 2)
1040 idx |= 0x5; /* vararg */
1041 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1042 idx |= 0x20; /* hasthis */
1044 idx |= 0x10; /* generic */
1045 sigbuffer_add_byte (&buf, idx);
1047 sigbuffer_add_value (&buf, ngparams);
1048 sigbuffer_add_value (&buf, nparams + notypes);
1049 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1052 encode_reflection_type (assembly, mb->rtype, &buf, error);
1055 for (i = 0; i < nparams; ++i) {
1056 MonoArray *modreq = NULL;
1057 MonoArray *modopt = NULL;
1058 MonoReflectionType *pt;
1060 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1061 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1062 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1063 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1064 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1067 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1068 encode_reflection_type (assembly, pt, &buf, error);
1073 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1074 for (i = 0; i < notypes; ++i) {
1075 MonoReflectionType *pt;
1077 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1078 encode_reflection_type (assembly, pt, &buf, error);
1083 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1085 sigbuffer_free (&buf);
1090 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1092 MONO_REQ_GC_UNSAFE_MODE;
1094 mono_error_init (error);
1096 MonoDynamicTable *table;
1098 guint32 idx, sig_idx;
1099 guint nl = mono_array_length (ilgen->locals);
1103 sigbuffer_init (&buf, 32);
1104 sigbuffer_add_value (&buf, 0x07);
1105 sigbuffer_add_value (&buf, nl);
1106 for (i = 0; i < nl; ++i) {
1107 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1110 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1112 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1113 if (!is_ok (error)) {
1114 sigbuffer_free (&buf);
1118 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1119 sigbuffer_free (&buf);
1121 if (assembly->standalonesig_cache == NULL)
1122 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1123 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1127 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1128 idx = table->next_idx ++;
1130 alloc_table (table, table->rows);
1131 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1133 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1135 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1141 method_count_clauses (MonoReflectionILGen *ilgen)
1143 MONO_REQ_GC_UNSAFE_MODE;
1145 guint32 num_clauses = 0;
1148 MonoILExceptionInfo *ex_info;
1149 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1150 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1151 if (ex_info->handlers)
1152 num_clauses += mono_array_length (ex_info->handlers);
1160 #ifndef DISABLE_REFLECTION_EMIT
1161 static MonoExceptionClause*
1162 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1164 MONO_REQ_GC_UNSAFE_MODE;
1166 mono_error_init (error);
1168 MonoExceptionClause *clauses;
1169 MonoExceptionClause *clause;
1170 MonoILExceptionInfo *ex_info;
1171 MonoILExceptionBlock *ex_block;
1172 guint32 finally_start;
1173 int i, j, clause_index;;
1175 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1178 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1179 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1180 finally_start = ex_info->start + ex_info->len;
1181 if (!ex_info->handlers)
1183 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1184 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1185 clause = &(clauses [clause_index]);
1187 clause->flags = ex_block->type;
1188 clause->try_offset = ex_info->start;
1190 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1191 clause->try_len = finally_start - ex_info->start;
1193 clause->try_len = ex_info->len;
1194 clause->handler_offset = ex_block->start;
1195 clause->handler_len = ex_block->len;
1196 if (ex_block->extype) {
1197 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1199 if (!is_ok (error)) {
1200 image_g_free (image, clauses);
1203 clause->data.catch_class = mono_class_from_mono_type (extype);
1205 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1206 clause->data.filter_offset = ex_block->filter_offset;
1208 clause->data.filter_offset = 0;
1210 finally_start = ex_block->start + ex_block->len;
1218 #endif /* !DISABLE_REFLECTION_EMIT */
1221 * method_encode_code:
1223 * @assembly the assembly
1224 * @mb the managed MethodBuilder
1225 * @error set on error
1227 * Note that the return value is not sensible if @error is set.
1230 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1232 MONO_REQ_GC_UNSAFE_MODE;
1237 gint32 max_stack, i;
1238 gint32 num_locals = 0;
1239 gint32 num_exception = 0;
1242 char fat_header [12];
1244 guint16 short_value;
1245 guint32 local_sig = 0;
1246 guint32 header_size = 12;
1249 mono_error_init (error);
1251 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1252 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1256 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1258 code = mb->ilgen->code;
1259 code_size = mb->ilgen->code_len;
1260 max_stack = mb->ilgen->max_stack;
1261 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1262 if (mb->ilgen->ex_handlers)
1263 num_exception = method_count_clauses (mb->ilgen);
1267 char *name = mono_string_to_utf8 (mb->name);
1268 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1269 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1275 code_size = mono_array_length (code);
1276 max_stack = 8; /* we probably need to run a verifier on the code... */
1279 stream_data_align (&assembly->code);
1281 /* check for exceptions, maxstack, locals */
1282 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1284 if (code_size < 64 && !(code_size & 1)) {
1285 flags = (code_size << 2) | 0x2;
1286 } else if (code_size < 32 && (code_size & 1)) {
1287 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1291 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1292 /* add to the fixup todo list */
1293 if (mb->ilgen && mb->ilgen->num_token_fixups)
1294 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1295 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1296 return assembly->text_rva + idx;
1300 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1301 return_val_if_nok (error, 0);
1304 * FIXME: need to set also the header size in fat_flags.
1305 * (and more sects and init locals flags)
1309 fat_flags |= METHOD_HEADER_MORE_SECTS;
1310 if (mb->init_locals)
1311 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1312 fat_header [0] = fat_flags;
1313 fat_header [1] = (header_size / 4 ) << 4;
1314 short_value = GUINT16_TO_LE (max_stack);
1315 memcpy (fat_header + 2, &short_value, 2);
1316 int_value = GUINT32_TO_LE (code_size);
1317 memcpy (fat_header + 4, &int_value, 4);
1318 int_value = GUINT32_TO_LE (local_sig);
1319 memcpy (fat_header + 8, &int_value, 4);
1320 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1321 /* add to the fixup todo list */
1322 if (mb->ilgen && mb->ilgen->num_token_fixups)
1323 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1325 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1326 if (num_exception) {
1327 unsigned char sheader [4];
1328 MonoILExceptionInfo * ex_info;
1329 MonoILExceptionBlock * ex_block;
1332 stream_data_align (&assembly->code);
1333 /* always use fat format for now */
1334 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1335 num_exception *= 6 * sizeof (guint32);
1336 num_exception += 4; /* include the size of the header */
1337 sheader [1] = num_exception & 0xff;
1338 sheader [2] = (num_exception >> 8) & 0xff;
1339 sheader [3] = (num_exception >> 16) & 0xff;
1340 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1341 /* fat header, so we are already aligned */
1343 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1344 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1345 if (ex_info->handlers) {
1346 int finally_start = ex_info->start + ex_info->len;
1347 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1349 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1351 val = GUINT32_TO_LE (ex_block->type);
1352 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1354 val = GUINT32_TO_LE (ex_info->start);
1355 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1356 /* need fault, too, probably */
1357 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1358 val = GUINT32_TO_LE (finally_start - ex_info->start);
1360 val = GUINT32_TO_LE (ex_info->len);
1361 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362 /* handler offset */
1363 val = GUINT32_TO_LE (ex_block->start);
1364 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1366 val = GUINT32_TO_LE (ex_block->len);
1367 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1368 finally_start = ex_block->start + ex_block->len;
1369 if (ex_block->extype) {
1370 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1371 return_val_if_nok (error, 0);
1373 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1375 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1376 val = ex_block->filter_offset;
1380 val = GUINT32_TO_LE (val);
1381 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1382 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1383 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1386 g_error ("No clauses for ex info block %d", i);
1390 return assembly->text_rva + idx;
1394 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1396 MONO_REQ_GC_NEUTRAL_MODE;
1399 MonoDynamicTable *table;
1402 table = &assembly->tables [table_idx];
1404 g_assert (col < table->columns);
1406 values = table->values + table->columns;
1407 for (i = 1; i <= table->rows; ++i) {
1408 if (values [col] == token)
1410 values += table->columns;
1416 * LOCKING: Acquires the loader lock.
1418 static MonoCustomAttrInfo*
1419 lookup_custom_attr (MonoImage *image, gpointer member)
1421 MONO_REQ_GC_NEUTRAL_MODE;
1423 MonoCustomAttrInfo* res;
1425 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1430 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1436 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1438 MONO_REQ_GC_UNSAFE_MODE;
1440 /* FIXME: Need to do more checks */
1441 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1442 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1444 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1451 static MonoCustomAttrInfo*
1452 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1454 MONO_REQ_GC_UNSAFE_MODE;
1456 int i, index, count, not_visible;
1457 MonoCustomAttrInfo *ainfo;
1458 MonoReflectionCustomAttr *cattr;
1462 /* FIXME: check in assembly the Run flag is set */
1464 count = mono_array_length (cattrs);
1466 /* Skip nonpublic attributes since MS.NET seems to do the same */
1467 /* FIXME: This needs to be done more globally */
1469 for (i = 0; i < count; ++i) {
1470 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471 if (!custom_attr_visible (image, cattr))
1474 count -= not_visible;
1476 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1478 ainfo->image = image;
1479 ainfo->num_attrs = count;
1480 ainfo->cached = alloc_img != NULL;
1482 for (i = 0; i < count; ++i) {
1483 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484 if (custom_attr_visible (image, cattr)) {
1485 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1486 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1487 ainfo->attrs [index].ctor = cattr->ctor->method;
1488 ainfo->attrs [index].data = saved;
1489 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1497 #ifndef DISABLE_REFLECTION_EMIT
1499 * LOCKING: Acquires the loader lock.
1502 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1504 MONO_REQ_GC_UNSAFE_MODE;
1506 MonoCustomAttrInfo *ainfo, *tmp;
1508 if (!cattrs || !mono_array_length (cattrs))
1511 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1513 mono_loader_lock ();
1514 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1516 mono_custom_attrs_free (tmp);
1517 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1518 mono_loader_unlock ();
1524 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1526 MONO_REQ_GC_NEUTRAL_MODE;
1528 if (ainfo && !ainfo->cached)
1533 * idx is the table index of the object
1534 * type is one of MONO_CUSTOM_ATTR_*
1537 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1539 MONO_REQ_GC_UNSAFE_MODE;
1541 MonoDynamicTable *table;
1542 MonoReflectionCustomAttr *cattr;
1544 guint32 count, i, token;
1546 char *p = blob_size;
1548 mono_error_init (error);
1550 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1553 count = mono_array_length (cattrs);
1554 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1555 table->rows += count;
1556 alloc_table (table, table->rows);
1557 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1558 idx <<= MONO_CUSTOM_ATTR_BITS;
1560 for (i = 0; i < count; ++i) {
1561 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1562 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1563 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1564 if (!mono_error_ok (error)) goto fail;
1565 type = mono_metadata_token_index (token);
1566 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1567 switch (mono_metadata_token_table (token)) {
1568 case MONO_TABLE_METHOD:
1569 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1571 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1572 * method, not the one returned by mono_image_create_token ().
1574 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1576 case MONO_TABLE_MEMBERREF:
1577 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1580 g_warning ("got wrong token in custom attr");
1583 values [MONO_CUSTOM_ATTR_TYPE] = type;
1585 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1586 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1587 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1588 values += MONO_CUSTOM_ATTR_SIZE;
1599 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1601 MONO_REQ_GC_UNSAFE_MODE;
1603 MonoDynamicTable *table;
1605 guint32 count, i, idx;
1606 MonoReflectionPermissionSet *perm;
1611 count = mono_array_length (permissions);
1612 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1613 table->rows += count;
1614 alloc_table (table, table->rows);
1616 for (i = 0; i < mono_array_length (permissions); ++i) {
1617 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1619 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1621 idx = mono_metadata_token_index (parent_token);
1622 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1623 switch (mono_metadata_token_table (parent_token)) {
1624 case MONO_TABLE_TYPEDEF:
1625 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1627 case MONO_TABLE_METHOD:
1628 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1630 case MONO_TABLE_ASSEMBLY:
1631 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1634 g_assert_not_reached ();
1637 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1638 values [MONO_DECL_SECURITY_PARENT] = idx;
1639 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1646 * Fill in the MethodDef and ParamDef tables for a method.
1647 * This is used for both normal methods and constructors.
1650 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1652 MONO_REQ_GC_UNSAFE_MODE;
1654 MonoDynamicTable *table;
1658 mono_error_init (error);
1660 /* room in this table is already allocated */
1661 table = &assembly->tables [MONO_TABLE_METHOD];
1662 *mb->table_idx = table->next_idx ++;
1663 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1664 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1665 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1666 values [MONO_METHOD_FLAGS] = mb->attrs;
1667 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1668 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1669 return_val_if_nok (error, FALSE);
1670 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1671 return_val_if_nok (error, FALSE);
1673 table = &assembly->tables [MONO_TABLE_PARAM];
1674 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1676 mono_image_add_decl_security (assembly,
1677 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1680 MonoDynamicTable *mtable;
1683 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1684 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1687 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1688 if (mono_array_get (mb->pinfo, gpointer, i))
1691 table->rows += count;
1692 alloc_table (table, table->rows);
1693 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1694 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1695 MonoReflectionParamBuilder *pb;
1696 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1697 values [MONO_PARAM_FLAGS] = pb->attrs;
1698 values [MONO_PARAM_SEQUENCE] = i;
1699 if (pb->name != NULL) {
1700 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1702 values [MONO_PARAM_NAME] = 0;
1704 values += MONO_PARAM_SIZE;
1705 if (pb->marshal_info) {
1707 alloc_table (mtable, mtable->rows);
1708 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1709 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1710 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1711 return_val_if_nok (error, FALSE);
1713 pb->table_idx = table->next_idx++;
1714 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1715 guint32 field_type = 0;
1716 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1718 alloc_table (mtable, mtable->rows);
1719 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1720 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1721 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1722 mvalues [MONO_CONSTANT_TYPE] = field_type;
1723 mvalues [MONO_CONSTANT_PADDING] = 0;
1732 #ifndef DISABLE_REFLECTION_EMIT
1734 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1736 MONO_REQ_GC_UNSAFE_MODE;
1738 mono_error_init (error);
1739 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1741 rmb->ilgen = mb->ilgen;
1742 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1743 return_val_if_nok (error, FALSE);
1744 rmb->parameters = mb->parameters;
1745 rmb->generic_params = mb->generic_params;
1746 rmb->generic_container = mb->generic_container;
1747 rmb->opt_types = NULL;
1748 rmb->pinfo = mb->pinfo;
1749 rmb->attrs = mb->attrs;
1750 rmb->iattrs = mb->iattrs;
1751 rmb->call_conv = mb->call_conv;
1752 rmb->code = mb->code;
1753 rmb->type = mb->type;
1754 rmb->name = mb->name;
1755 rmb->table_idx = &mb->table_idx;
1756 rmb->init_locals = mb->init_locals;
1757 rmb->skip_visibility = FALSE;
1758 rmb->return_modreq = mb->return_modreq;
1759 rmb->return_modopt = mb->return_modopt;
1760 rmb->param_modreq = mb->param_modreq;
1761 rmb->param_modopt = mb->param_modopt;
1762 rmb->permissions = mb->permissions;
1763 rmb->mhandle = mb->mhandle;
1768 rmb->charset = mb->charset;
1769 rmb->extra_flags = mb->extra_flags;
1770 rmb->native_cc = mb->native_cc;
1771 rmb->dllentry = mb->dllentry;
1779 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1781 MONO_REQ_GC_UNSAFE_MODE;
1783 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1785 mono_error_init (error);
1787 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1789 rmb->ilgen = mb->ilgen;
1790 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1791 return_val_if_nok (error, FALSE);
1792 rmb->parameters = mb->parameters;
1793 rmb->generic_params = NULL;
1794 rmb->generic_container = NULL;
1795 rmb->opt_types = NULL;
1796 rmb->pinfo = mb->pinfo;
1797 rmb->attrs = mb->attrs;
1798 rmb->iattrs = mb->iattrs;
1799 rmb->call_conv = mb->call_conv;
1801 rmb->type = mb->type;
1802 rmb->name = mono_string_new (mono_domain_get (), name);
1803 rmb->table_idx = &mb->table_idx;
1804 rmb->init_locals = mb->init_locals;
1805 rmb->skip_visibility = FALSE;
1806 rmb->return_modreq = NULL;
1807 rmb->return_modopt = NULL;
1808 rmb->param_modreq = mb->param_modreq;
1809 rmb->param_modopt = mb->param_modopt;
1810 rmb->permissions = mb->permissions;
1811 rmb->mhandle = mb->mhandle;
1819 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1821 MONO_REQ_GC_UNSAFE_MODE;
1823 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1825 rmb->ilgen = mb->ilgen;
1826 rmb->rtype = mb->rtype;
1827 rmb->parameters = mb->parameters;
1828 rmb->generic_params = NULL;
1829 rmb->generic_container = NULL;
1830 rmb->opt_types = NULL;
1832 rmb->attrs = mb->attrs;
1834 rmb->call_conv = mb->call_conv;
1836 rmb->type = (MonoObject *) mb->owner;
1837 rmb->name = mb->name;
1838 rmb->table_idx = NULL;
1839 rmb->init_locals = mb->init_locals;
1840 rmb->skip_visibility = mb->skip_visibility;
1841 rmb->return_modreq = NULL;
1842 rmb->return_modopt = NULL;
1843 rmb->param_modreq = NULL;
1844 rmb->param_modopt = NULL;
1845 rmb->permissions = NULL;
1846 rmb->mhandle = mb->mhandle;
1853 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1855 MONO_REQ_GC_UNSAFE_MODE;
1857 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1858 MonoDynamicTable *table;
1861 MonoReflectionMethod *m;
1864 mono_error_init (error);
1866 if (!mb->override_methods)
1869 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1870 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1872 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1874 alloc_table (table, table->rows);
1875 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1876 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1877 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1879 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1880 return_val_if_nok (error, FALSE);
1882 switch (mono_metadata_token_table (tok)) {
1883 case MONO_TABLE_MEMBERREF:
1884 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1886 case MONO_TABLE_METHOD:
1887 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1890 g_assert_not_reached ();
1892 values [MONO_METHODIMPL_DECLARATION] = tok;
1898 #ifndef DISABLE_REFLECTION_EMIT
1900 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1902 MONO_REQ_GC_UNSAFE_MODE;
1904 MonoDynamicTable *table;
1906 ReflectionMethodBuilder rmb;
1909 mono_error_init (error);
1911 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1912 !mono_image_basic_method (&rmb, assembly, error))
1915 mb->table_idx = *rmb.table_idx;
1917 if (mb->dll) { /* It's a P/Invoke method */
1919 /* map CharSet values to on-disk values */
1920 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1921 int extra_flags = mb->extra_flags;
1922 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1924 alloc_table (table, table->rows);
1925 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1927 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1928 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1930 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1932 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1933 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1934 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1935 table = &assembly->tables [MONO_TABLE_MODULEREF];
1937 alloc_table (table, table->rows);
1938 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1939 values [MONO_IMPLMAP_SCOPE] = table->rows;
1943 if (mb->generic_params) {
1944 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1945 table->rows += mono_array_length (mb->generic_params);
1946 alloc_table (table, table->rows);
1947 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1948 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1950 mono_image_get_generic_param_info (
1951 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1959 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1961 MONO_REQ_GC_UNSAFE_MODE;
1963 ReflectionMethodBuilder rmb;
1965 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1968 if (!mono_image_basic_method (&rmb, assembly, error))
1971 mb->table_idx = *rmb.table_idx;
1978 type_get_fully_qualified_name (MonoType *type)
1980 MONO_REQ_GC_NEUTRAL_MODE;
1982 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1986 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1988 MONO_REQ_GC_UNSAFE_MODE;
1993 klass = mono_class_from_mono_type (type);
1995 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1996 ta = klass->image->assembly;
1997 if (assembly_is_dynamic (ta) || (ta == ass)) {
1998 if (klass->generic_class || klass->generic_container)
1999 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2000 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2005 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2008 #ifndef DISABLE_REFLECTION_EMIT
2009 /*field_image is the image to which the eventual custom mods have been encoded against*/
2011 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2013 MONO_REQ_GC_NEUTRAL_MODE;
2016 guint32 idx, i, token;
2018 if (!assembly->save)
2021 sigbuffer_init (&buf, 32);
2023 sigbuffer_add_value (&buf, 0x06);
2024 /* encode custom attributes before the type */
2025 if (type->num_mods) {
2026 for (i = 0; i < type->num_mods; ++i) {
2029 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2030 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2032 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2034 token = type->modifiers [i].token;
2037 if (type->modifiers [i].required)
2038 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2040 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2042 sigbuffer_add_value (&buf, token);
2045 encode_type (assembly, type, &buf);
2046 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2047 sigbuffer_free (&buf);
2053 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2055 MONO_REQ_GC_UNSAFE_MODE;
2057 mono_error_init (error);
2061 guint32 typespec = 0;
2065 init_type_builder_generics (fb->type, error);
2066 return_val_if_nok (error, 0);
2068 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2069 return_val_if_nok (error, 0);
2070 klass = mono_class_from_mono_type (type);
2072 sigbuffer_init (&buf, 32);
2074 sigbuffer_add_value (&buf, 0x06);
2075 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2078 /* encode custom attributes before the type */
2080 if (klass->generic_container)
2081 typespec = create_typespec (assembly, type);
2084 MonoGenericClass *gclass;
2085 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2086 encode_generic_class (assembly, gclass, &buf);
2088 encode_type (assembly, type, &buf);
2090 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2091 sigbuffer_free (&buf);
2094 sigbuffer_free (&buf);
2099 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2101 MONO_REQ_GC_UNSAFE_MODE;
2103 char blob_size [64];
2104 char *b = blob_size;
2107 guint32 idx = 0, len = 0, dummy = 0;
2109 buf = (char *)g_malloc (64);
2111 *ret_type = MONO_TYPE_CLASS;
2113 box_val = (char*)&dummy;
2115 box_val = ((char*)val) + sizeof (MonoObject);
2116 *ret_type = val->vtable->klass->byval_arg.type;
2119 switch (*ret_type) {
2120 case MONO_TYPE_BOOLEAN:
2125 case MONO_TYPE_CHAR:
2142 case MONO_TYPE_VALUETYPE: {
2143 MonoClass *klass = val->vtable->klass;
2145 if (klass->enumtype) {
2146 *ret_type = mono_class_enum_basetype (klass)->type;
2148 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2151 g_error ("we can't encode valuetypes, we should have never reached this line");
2154 case MONO_TYPE_CLASS:
2156 case MONO_TYPE_STRING: {
2157 MonoString *str = (MonoString*)val;
2158 /* there is no signature */
2159 len = str->length * 2;
2160 mono_metadata_encode_value (len, b, &b);
2161 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2163 char *swapped = g_malloc (2 * mono_string_length (str));
2164 const char *p = (const char*)mono_string_chars (str);
2166 swap_with_size (swapped, p, 2, mono_string_length (str));
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2171 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2177 case MONO_TYPE_GENERICINST:
2178 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2181 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2184 /* there is no signature */
2185 mono_metadata_encode_value (len, b, &b);
2186 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2187 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2188 swap_with_size (blob_size, box_val, len, 1);
2189 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2191 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2199 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2201 MONO_REQ_GC_UNSAFE_MODE;
2203 mono_error_init (error);
2209 sigbuffer_init (&buf, 32);
2211 sigbuffer_add_value (&buf, minfo->type);
2213 switch (minfo->type) {
2214 case MONO_NATIVE_BYVALTSTR:
2215 case MONO_NATIVE_BYVALARRAY:
2216 sigbuffer_add_value (&buf, minfo->count);
2218 case MONO_NATIVE_LPARRAY:
2219 if (minfo->eltype || minfo->has_size) {
2220 sigbuffer_add_value (&buf, minfo->eltype);
2221 if (minfo->has_size) {
2222 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2223 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2225 /* LAMESPEC: ElemMult is undocumented */
2226 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2230 case MONO_NATIVE_SAFEARRAY:
2232 sigbuffer_add_value (&buf, minfo->eltype);
2234 case MONO_NATIVE_CUSTOM:
2236 str = mono_string_to_utf8 (minfo->guid);
2238 sigbuffer_add_value (&buf, len);
2239 sigbuffer_add_mem (&buf, str, len);
2242 sigbuffer_add_value (&buf, 0);
2244 /* native type name */
2245 sigbuffer_add_value (&buf, 0);
2246 /* custom marshaler type name */
2247 if (minfo->marshaltype || minfo->marshaltyperef) {
2248 if (minfo->marshaltyperef) {
2249 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2250 if (!is_ok (error)) {
2251 sigbuffer_free (&buf);
2254 str = type_get_fully_qualified_name (marshaltype);
2256 str = mono_string_to_utf8 (minfo->marshaltype);
2258 sigbuffer_add_value (&buf, len);
2259 sigbuffer_add_mem (&buf, str, len);
2262 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2263 sigbuffer_add_value (&buf, 0);
2265 if (minfo->mcookie) {
2266 str = mono_string_to_utf8 (minfo->mcookie);
2268 sigbuffer_add_value (&buf, len);
2269 sigbuffer_add_mem (&buf, str, len);
2272 sigbuffer_add_value (&buf, 0);
2278 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2279 sigbuffer_free (&buf);
2284 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2286 MONO_REQ_GC_UNSAFE_MODE;
2288 mono_error_init (error);
2290 MonoDynamicTable *table;
2293 /* maybe this fixup should be done in the C# code */
2294 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2295 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2296 table = &assembly->tables [MONO_TABLE_FIELD];
2297 fb->table_idx = table->next_idx ++;
2298 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2299 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2300 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2301 values [MONO_FIELD_FLAGS] = fb->attrs;
2302 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2303 return_if_nok (error);
2306 if (fb->offset != -1) {
2307 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2309 alloc_table (table, table->rows);
2310 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2311 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2312 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2314 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2315 MonoTypeEnum field_type = (MonoTypeEnum)0;
2316 table = &assembly->tables [MONO_TABLE_CONSTANT];
2318 alloc_table (table, table->rows);
2319 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2320 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2321 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2322 values [MONO_CONSTANT_TYPE] = field_type;
2323 values [MONO_CONSTANT_PADDING] = 0;
2325 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2327 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2329 alloc_table (table, table->rows);
2330 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2331 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2333 * We store it in the code section because it's simpler for now.
2336 if (mono_array_length (fb->rva_data) >= 10)
2337 stream_data_align (&assembly->code);
2338 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2340 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2341 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2343 if (fb->marshal_info) {
2344 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2346 alloc_table (table, table->rows);
2347 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2348 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2349 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2350 return_if_nok (error);
2355 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2357 MONO_REQ_GC_UNSAFE_MODE;
2359 mono_error_init (error);
2362 guint32 nparams = 0;
2363 MonoReflectionMethodBuilder *mb = fb->get_method;
2364 MonoReflectionMethodBuilder *smb = fb->set_method;
2367 if (mb && mb->parameters)
2368 nparams = mono_array_length (mb->parameters);
2369 if (!mb && smb && smb->parameters)
2370 nparams = mono_array_length (smb->parameters) - 1;
2371 sigbuffer_init (&buf, 32);
2372 if (fb->call_conv & 0x20)
2373 sigbuffer_add_byte (&buf, 0x28);
2375 sigbuffer_add_byte (&buf, 0x08);
2376 sigbuffer_add_value (&buf, nparams);
2378 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2381 for (i = 0; i < nparams; ++i) {
2382 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2383 encode_reflection_type (assembly, pt, &buf, error);
2387 } else if (smb && smb->parameters) {
2388 /* the property type is the last param */
2389 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2393 for (i = 0; i < nparams; ++i) {
2394 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2395 encode_reflection_type (assembly, pt, &buf, error);
2400 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2405 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2406 sigbuffer_free (&buf);
2409 sigbuffer_free (&buf);
2414 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2416 MONO_REQ_GC_UNSAFE_MODE;
2418 mono_error_init (error);
2420 MonoDynamicTable *table;
2422 guint num_methods = 0;
2426 * we need to set things in the following tables:
2427 * PROPERTYMAP (info already filled in _get_type_info ())
2428 * PROPERTY (rows already preallocated in _get_type_info ())
2429 * METHOD (method info already done with the generic method code)
2433 table = &assembly->tables [MONO_TABLE_PROPERTY];
2434 pb->table_idx = table->next_idx ++;
2435 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2436 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2437 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2438 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2439 return_if_nok (error);
2442 /* FIXME: we still don't handle 'other' methods */
2443 if (pb->get_method) num_methods ++;
2444 if (pb->set_method) num_methods ++;
2446 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2447 table->rows += num_methods;
2448 alloc_table (table, table->rows);
2450 if (pb->get_method) {
2451 semaidx = table->next_idx ++;
2452 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2453 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2454 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2455 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2457 if (pb->set_method) {
2458 semaidx = table->next_idx ++;
2459 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2460 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2461 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2462 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2464 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2465 MonoTypeEnum field_type = (MonoTypeEnum)0;
2466 table = &assembly->tables [MONO_TABLE_CONSTANT];
2468 alloc_table (table, table->rows);
2469 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2470 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2471 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2472 values [MONO_CONSTANT_TYPE] = field_type;
2473 values [MONO_CONSTANT_PADDING] = 0;
2478 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2480 MONO_REQ_GC_UNSAFE_MODE;
2482 MonoDynamicTable *table;
2484 guint num_methods = 0;
2488 * we need to set things in the following tables:
2489 * EVENTMAP (info already filled in _get_type_info ())
2490 * EVENT (rows already preallocated in _get_type_info ())
2491 * METHOD (method info already done with the generic method code)
2494 table = &assembly->tables [MONO_TABLE_EVENT];
2495 eb->table_idx = table->next_idx ++;
2496 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2497 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2498 values [MONO_EVENT_FLAGS] = eb->attrs;
2499 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2500 return_if_nok (error);
2501 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2504 * FIXME: we still don't handle 'other' methods
2506 if (eb->add_method) num_methods ++;
2507 if (eb->remove_method) num_methods ++;
2508 if (eb->raise_method) num_methods ++;
2510 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2511 table->rows += num_methods;
2512 alloc_table (table, table->rows);
2514 if (eb->add_method) {
2515 semaidx = table->next_idx ++;
2516 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2517 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2518 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2519 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2521 if (eb->remove_method) {
2522 semaidx = table->next_idx ++;
2523 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2524 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2525 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2526 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2528 if (eb->raise_method) {
2529 semaidx = table->next_idx ++;
2530 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2531 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2532 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2533 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2538 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2540 MONO_REQ_GC_UNSAFE_MODE;
2542 mono_error_init (error);
2544 MonoDynamicTable *table;
2545 guint32 num_constraints, i;
2549 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2550 num_constraints = gparam->iface_constraints ?
2551 mono_array_length (gparam->iface_constraints) : 0;
2552 table->rows += num_constraints;
2553 if (gparam->base_type)
2555 alloc_table (table, table->rows);
2557 if (gparam->base_type) {
2558 table_idx = table->next_idx ++;
2559 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2561 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2562 return_if_nok (error);
2563 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2564 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2567 for (i = 0; i < num_constraints; i++) {
2568 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2569 gparam->iface_constraints, gpointer, i);
2571 table_idx = table->next_idx ++;
2572 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2574 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2575 return_if_nok (error);
2577 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2578 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2583 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2585 MONO_REQ_GC_UNSAFE_MODE;
2587 GenericParamTableEntry *entry;
2590 * The GenericParam table must be sorted according to the `owner' field.
2591 * We need to do this sorting prior to writing the GenericParamConstraint
2592 * table, since we have to use the final GenericParam table indices there
2593 * and they must also be sorted.
2596 entry = g_new0 (GenericParamTableEntry, 1);
2597 entry->owner = owner;
2598 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2599 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2600 entry->gparam = gparam;
2602 g_ptr_array_add (assembly->gen_params, entry);
2606 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2608 MONO_REQ_GC_UNSAFE_MODE;
2610 MonoDynamicTable *table;
2611 MonoGenericParam *param;
2615 mono_error_init (error);
2617 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2618 table_idx = table->next_idx ++;
2619 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2621 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2622 return_val_if_nok (error, FALSE);
2624 param = gparam_type->data.generic_param;
2626 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2627 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2628 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2629 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2631 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2634 encode_constraints (entry->gparam, table_idx, assembly, error);
2635 return_val_if_nok (error, FALSE);
2641 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2643 MONO_REQ_GC_UNSAFE_MODE;
2645 MonoDynamicTable *table;
2648 guint32 cols [MONO_ASSEMBLY_SIZE];
2652 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2655 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2656 table = &assembly->tables [MONO_TABLE_MODULEREF];
2657 token = table->next_idx ++;
2659 alloc_table (table, table->rows);
2660 values = table->values + token * MONO_MODULEREF_SIZE;
2661 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2663 token <<= MONO_RESOLUTION_SCOPE_BITS;
2664 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2665 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2670 if (assembly_is_dynamic (image->assembly))
2672 memset (cols, 0, sizeof (cols));
2674 /* image->assembly->image is the manifest module */
2675 image = image->assembly->image;
2676 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2679 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2680 token = table->next_idx ++;
2682 alloc_table (table, table->rows);
2683 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2684 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2685 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2686 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2687 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2688 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2689 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2690 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2691 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2693 if (strcmp ("", image->assembly->aname.culture)) {
2694 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2695 image->assembly->aname.culture);
2698 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2699 guchar pubtoken [9];
2701 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2702 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2704 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2706 token <<= MONO_RESOLUTION_SCOPE_BITS;
2707 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2708 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2713 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2715 MONO_REQ_GC_NEUTRAL_MODE;
2717 MonoDynamicTable *table;
2722 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2725 sigbuffer_init (&buf, 32);
2726 switch (type->type) {
2727 case MONO_TYPE_FNPTR:
2729 case MONO_TYPE_SZARRAY:
2730 case MONO_TYPE_ARRAY:
2732 case MONO_TYPE_MVAR:
2733 case MONO_TYPE_GENERICINST:
2734 encode_type (assembly, type, &buf);
2736 case MONO_TYPE_CLASS:
2737 case MONO_TYPE_VALUETYPE: {
2738 MonoClass *k = mono_class_from_mono_type (type);
2739 if (!k || !k->generic_container) {
2740 sigbuffer_free (&buf);
2743 encode_type (assembly, type, &buf);
2747 sigbuffer_free (&buf);
2751 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2752 if (assembly->save) {
2753 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2754 alloc_table (table, table->rows + 1);
2755 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2756 values [MONO_TYPESPEC_SIGNATURE] = token;
2758 sigbuffer_free (&buf);
2760 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2761 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2767 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2769 MONO_REQ_GC_UNSAFE_MODE;
2771 MonoDynamicTable *table;
2773 guint32 token, scope, enclosing;
2776 /* if the type requires a typespec, we must try that first*/
2777 if (try_typespec && (token = create_typespec (assembly, type)))
2779 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2782 klass = mono_class_from_mono_type (type);
2784 klass = mono_class_from_mono_type (type);
2787 * If it's in the same module and not a generic type parameter:
2789 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2790 (type->type != MONO_TYPE_MVAR)) {
2791 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2792 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2793 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2797 if (klass->nested_in) {
2798 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2799 /* get the typeref idx of the enclosing type */
2800 enclosing >>= MONO_TYPEDEFORREF_BITS;
2801 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2803 scope = resolution_scope_from_image (assembly, klass->image);
2805 table = &assembly->tables [MONO_TABLE_TYPEREF];
2806 if (assembly->save) {
2807 alloc_table (table, table->rows + 1);
2808 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2809 values [MONO_TYPEREF_SCOPE] = scope;
2810 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2811 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2813 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2814 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2816 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2821 * Despite the name, we handle also TypeSpec (with the above helper).
2824 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2826 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2829 #ifndef DISABLE_REFLECTION_EMIT
2831 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2833 MONO_REQ_GC_NEUTRAL_MODE;
2835 MonoDynamicTable *table;
2837 guint32 token, pclass;
2839 switch (parent & MONO_TYPEDEFORREF_MASK) {
2840 case MONO_TYPEDEFORREF_TYPEREF:
2841 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2843 case MONO_TYPEDEFORREF_TYPESPEC:
2844 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2846 case MONO_TYPEDEFORREF_TYPEDEF:
2847 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2850 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2853 /* extract the index */
2854 parent >>= MONO_TYPEDEFORREF_BITS;
2856 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2858 if (assembly->save) {
2859 alloc_table (table, table->rows + 1);
2860 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2861 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2862 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2863 values [MONO_MEMBERREF_SIGNATURE] = sig;
2866 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2873 * Insert a memberef row into the metadata: the token that point to the memberref
2874 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2875 * mono_image_get_fieldref_token()).
2876 * The sig param is an index to an already built signature.
2879 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2881 MONO_REQ_GC_NEUTRAL_MODE;
2883 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2884 return mono_image_add_memberef_row (assembly, parent, name, sig);
2889 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2891 MONO_REQ_GC_NEUTRAL_MODE;
2894 MonoMethodSignature *sig;
2896 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2898 if (create_typespec) {
2899 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2904 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2905 if (token && !create_typespec)
2908 g_assert (!method->is_inflated);
2911 * A methodref signature can't contain an unmanaged calling convention.
2913 sig = mono_metadata_signature_dup (mono_method_signature (method));
2914 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2915 sig->call_convention = MONO_CALL_DEFAULT;
2916 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2917 method->name, method_encode_signature (assembly, sig));
2919 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2922 if (create_typespec) {
2923 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2924 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2925 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2927 if (assembly->save) {
2930 alloc_table (table, table->rows + 1);
2931 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2932 values [MONO_METHODSPEC_METHOD] = token;
2933 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2936 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2938 /*methodspec and memberef tokens are diferent, */
2939 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2946 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2948 guint32 token, parent, sig;
2949 ReflectionMethodBuilder rmb;
2950 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2952 mono_error_init (error);
2953 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2957 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2961 * A methodref signature can't contain an unmanaged calling convention.
2962 * Since some flags are encoded as part of call_conv, we need to check against it.
2964 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2965 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2967 sig = method_builder_encode_signature (assembly, &rmb, error);
2968 return_val_if_nok (error, 0);
2970 if (tb->generic_params) {
2971 parent = create_generic_typespec (assembly, tb, error);
2972 return_val_if_nok (error, 0);
2974 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2975 return_val_if_nok (error, 0);
2977 parent = mono_image_typedef_or_ref (assembly, t);
2980 char *name = mono_string_to_utf8 (method->name);
2982 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2985 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2991 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2992 const gchar *name, guint32 sig)
2994 MonoDynamicTable *table;
2998 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3000 if (assembly->save) {
3001 alloc_table (table, table->rows + 1);
3002 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3003 values [MONO_MEMBERREF_CLASS] = original;
3004 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3005 values [MONO_MEMBERREF_SIGNATURE] = sig;
3008 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3015 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3019 guint32 nparams = mono_array_length (mb->generic_params);
3022 if (!assembly->save)
3025 sigbuffer_init (&buf, 32);
3027 sigbuffer_add_value (&buf, 0xa);
3028 sigbuffer_add_value (&buf, nparams);
3030 for (i = 0; i < nparams; i++) {
3031 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3032 sigbuffer_add_value (&buf, i);
3035 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3036 sigbuffer_free (&buf);
3041 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3043 MonoDynamicTable *table;
3045 guint32 token, mtoken = 0;
3047 mono_error_init (error);
3048 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3052 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3054 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3055 if (!mono_error_ok (error))
3058 switch (mono_metadata_token_table (mtoken)) {
3059 case MONO_TABLE_MEMBERREF:
3060 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3062 case MONO_TABLE_METHOD:
3063 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3066 g_assert_not_reached ();
3069 if (assembly->save) {
3070 alloc_table (table, table->rows + 1);
3071 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3072 values [MONO_METHODSPEC_METHOD] = mtoken;
3073 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3076 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3079 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3084 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3088 mono_error_init (error);
3090 if (mb->generic_params && create_methodspec)
3091 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3093 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3097 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3098 if (!mono_error_ok (error))
3100 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3105 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3107 guint32 token, parent, sig;
3108 ReflectionMethodBuilder rmb;
3110 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3112 mono_error_init (error);
3114 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3118 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3121 if (tb->generic_params) {
3122 parent = create_generic_typespec (assembly, tb, error);
3123 return_val_if_nok (error, 0);
3125 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3126 return_val_if_nok (error, 0);
3127 parent = mono_image_typedef_or_ref (assembly, type);
3130 name = mono_string_to_utf8 (rmb.name);
3131 sig = method_builder_encode_signature (assembly, &rmb, error);
3132 return_val_if_nok (error, 0);
3134 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3137 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3143 is_field_on_inst (MonoClassField *field)
3145 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3149 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3152 get_field_on_inst_generic_type (MonoClassField *field)
3154 MonoClass *klass, *gtd;
3155 MonoDynamicGenericClass *dgclass;
3158 g_assert (is_field_on_inst (field));
3160 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3162 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3163 field_index = field - dgclass->fields;
3164 return dgclass->field_generic_types [field_index];
3167 klass = field->parent;
3168 gtd = klass->generic_class->container_class;
3170 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3171 field_index = field - klass->fields;
3172 return gtd->fields [field_index].type;
3175 g_assert_not_reached ();
3179 #ifndef DISABLE_REFLECTION_EMIT
3181 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3187 g_assert (field->parent);
3189 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3193 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3194 int index = field - field->parent->fields;
3195 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3197 if (is_field_on_inst (field))
3198 type = get_field_on_inst_generic_type (field);
3200 type = mono_field_get_type (field);
3202 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3203 mono_field_get_name (field),
3204 fieldref_encode_signature (assembly, field->parent->image, type));
3205 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3210 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3214 MonoGenericClass *gclass;
3218 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3221 if (is_sre_field_builder (mono_object_class (f->fb))) {
3222 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3223 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3224 return_val_if_nok (error, 0);
3225 klass = mono_class_from_mono_type (type);
3226 gclass = type->data.generic_class;
3227 g_assert (gclass->is_dynamic);
3229 guint32 sig_token = field_encode_signature (assembly, fb, error);
3230 return_val_if_nok (error, 0);
3231 name = mono_string_to_utf8 (fb->name);
3232 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3234 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3236 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3238 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3239 return_val_if_nok (error, 0);
3240 klass = mono_class_from_mono_type (type);
3242 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3243 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3245 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3246 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3249 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3254 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3258 MonoGenericClass *gclass;
3261 mono_error_init (error);
3263 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3265 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3269 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3270 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3271 ReflectionMethodBuilder rmb;
3274 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3275 return_val_if_nok (error, 0);
3276 klass = mono_class_from_mono_type (type);
3278 gclass = type->data.generic_class;
3279 g_assert (gclass->is_dynamic);
3281 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3284 sig = method_builder_encode_signature (assembly, &rmb, error);
3285 return_val_if_nok (error, 0);
3287 name = mono_string_to_utf8 (rmb.name);
3289 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3291 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3292 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3294 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3295 return_val_if_nok (error, 0);
3296 klass = mono_class_from_mono_type (type);
3298 sig = method_encode_signature (assembly, mono_method_signature (mm));
3299 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3301 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3302 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3306 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3311 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3314 MonoGenericContext tmp_context;
3315 MonoType **type_argv;
3316 MonoGenericInst *ginst;
3317 MonoMethod *method, *inflated;
3320 mono_error_init (error);
3322 init_type_builder_generics ((MonoObject*)m->inst, error);
3323 return_val_if_nok (error, NULL);
3325 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3326 return_val_if_nok (error, NULL);
3328 klass = method->klass;
3330 if (m->method_args == NULL)
3333 if (method->is_inflated)
3334 method = ((MonoMethodInflated *) method)->declaring;
3336 count = mono_array_length (m->method_args);
3338 type_argv = g_new0 (MonoType *, count);
3339 for (i = 0; i < count; i++) {
3340 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3341 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3342 return_val_if_nok (error, NULL);
3344 ginst = mono_metadata_get_generic_inst (count, type_argv);
3347 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3348 tmp_context.method_inst = ginst;
3350 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3351 mono_error_assert_ok (error);
3356 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3358 guint32 sig, token = 0;
3362 mono_error_init (error);
3364 if (m->method_args) {
3365 MonoMethod *inflated;
3367 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3368 return_val_if_nok (error, 0);
3370 if (create_methodspec)
3371 token = mono_image_get_methodspec_token (assembly, inflated);
3373 token = mono_image_get_inflated_method_token (assembly, inflated);
3377 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3381 if (is_sre_method_builder (mono_object_class (m->mb))) {
3382 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3383 MonoGenericClass *gclass;
3384 ReflectionMethodBuilder rmb;
3387 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3388 return_val_if_nok (error, 0);
3389 klass = mono_class_from_mono_type (type);
3390 gclass = type->data.generic_class;
3391 g_assert (gclass->is_dynamic);
3393 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3396 sig = method_builder_encode_signature (assembly, &rmb, error);
3397 return_val_if_nok (error, 0);
3399 name = mono_string_to_utf8 (rmb.name);
3401 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3403 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3404 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3406 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3407 return_val_if_nok (error, 0);
3408 klass = mono_class_from_mono_type (type);
3410 sig = method_encode_signature (assembly, mono_method_signature (mm));
3411 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3413 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3414 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3417 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3422 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3426 guint32 nparams = context->method_inst->type_argc;
3429 if (!assembly->save)
3432 sigbuffer_init (&buf, 32);
3434 * FIXME: vararg, explicit_this, differenc call_conv values...
3436 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3437 sigbuffer_add_value (&buf, nparams);
3439 for (i = 0; i < nparams; i++)
3440 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3442 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3443 sigbuffer_free (&buf);
3448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3450 MonoDynamicTable *table;
3452 guint32 token, mtoken = 0, sig;
3453 MonoMethodInflated *imethod;
3454 MonoMethod *declaring;
3456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3458 g_assert (method->is_inflated);
3459 imethod = (MonoMethodInflated *) method;
3460 declaring = imethod->declaring;
3462 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3463 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3465 if (!mono_method_signature (declaring)->generic_param_count)
3468 switch (mono_metadata_token_table (mtoken)) {
3469 case MONO_TABLE_MEMBERREF:
3470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3472 case MONO_TABLE_METHOD:
3473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3476 g_assert_not_reached ();
3479 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3481 if (assembly->save) {
3482 alloc_table (table, table->rows + 1);
3483 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3484 values [MONO_METHODSPEC_METHOD] = mtoken;
3485 values [MONO_METHODSPEC_SIGNATURE] = sig;
3488 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3497 MonoMethodInflated *imethod;
3500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3504 g_assert (method->is_inflated);
3505 imethod = (MonoMethodInflated *) method;
3507 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3508 token = method_encode_methodspec (assembly, method);
3510 guint32 sig = method_encode_signature (
3511 assembly, mono_method_signature (imethod->declaring));
3512 token = mono_image_get_memberref_token (
3513 assembly, &method->klass->byval_arg, method->name, sig);
3516 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3523 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3526 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3527 token = mono_image_get_memberref_token (
3528 assembly, &m->klass->byval_arg, m->name, sig);
3534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3536 MonoDynamicTable *table;
3545 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3546 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3547 * Because of this, we must not insert it into the `typeref' hash table.
3549 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3550 return_val_if_nok (error, 0);
3551 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3555 sigbuffer_init (&buf, 32);
3557 g_assert (tb->generic_params);
3558 klass = mono_class_from_mono_type (type);
3560 if (tb->generic_container) {
3561 if (!mono_reflection_create_generic_class (tb, error))
3565 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3566 g_assert (klass->generic_container);
3567 sigbuffer_add_value (&buf, klass->byval_arg.type);
3568 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3570 count = mono_array_length (tb->generic_params);
3571 sigbuffer_add_value (&buf, count);
3572 for (i = 0; i < count; i++) {
3573 MonoReflectionGenericParam *gparam;
3575 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3576 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3580 encode_type (assembly, gparam_type, &buf);
3583 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3585 if (assembly->save) {
3586 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3587 alloc_table (table, table->rows + 1);
3588 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3589 values [MONO_TYPESPEC_SIGNATURE] = token;
3591 sigbuffer_free (&buf);
3593 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3594 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3598 sigbuffer_free (&buf);
3603 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3606 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3608 int i, count, len, pos;
3611 mono_error_init (error);
3615 count += mono_array_length (modreq);
3617 count += mono_array_length (modopt);
3620 return mono_metadata_type_dup (NULL, type);
3622 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3623 t = (MonoType *)g_malloc (len);
3624 memcpy (t, type, MONO_SIZEOF_TYPE);
3626 t->num_mods = count;
3629 for (i = 0; i < mono_array_length (modreq); ++i) {
3630 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3633 t->modifiers [pos].required = 1;
3634 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3639 for (i = 0; i < mono_array_length (modopt); ++i) {
3640 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3643 t->modifiers [pos].required = 0;
3644 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3656 init_type_builder_generics (MonoObject *type, MonoError *error)
3658 MonoReflectionTypeBuilder *tb;
3660 mono_error_init (error);
3662 if (!is_sre_type_builder(mono_object_class (type)))
3664 tb = (MonoReflectionTypeBuilder *)type;
3666 if (tb && tb->generic_container)
3667 mono_reflection_create_generic_class (tb, error);
3671 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3673 MonoDynamicTable *table;
3674 MonoType *custom = NULL, *type;
3676 guint32 token, pclass, parent, sig;
3679 mono_error_init (error);
3681 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3685 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3686 return_val_if_nok (error, 0);
3687 /* FIXME: is this call necessary? */
3688 mono_class_from_mono_type (typeb);
3690 /*FIXME this is one more layer of ugliness due how types are created.*/
3691 init_type_builder_generics (fb->type, error);
3692 return_val_if_nok (error, 0);
3694 /* fb->type does not include the custom modifiers */
3695 /* FIXME: We should do this in one place when a fieldbuilder is created */
3696 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3697 return_val_if_nok (error, 0);
3699 if (fb->modreq || fb->modopt) {
3700 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3701 return_val_if_nok (error, 0);
3704 sig = fieldref_encode_signature (assembly, NULL, type);
3707 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3708 return_val_if_nok (error, 0);
3709 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3711 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3712 parent >>= MONO_TYPEDEFORREF_BITS;
3714 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3716 name = mono_string_to_utf8 (fb->name);
3718 if (assembly->save) {
3719 alloc_table (table, table->rows + 1);
3720 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3721 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3722 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3723 values [MONO_MEMBERREF_SIGNATURE] = sig;
3726 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3728 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3734 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3740 mono_error_init (error);
3742 if (!assembly->save)
3745 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3746 g_assert (helper->type == 2);
3748 if (helper->arguments)
3749 nargs = mono_array_length (helper->arguments);
3753 sigbuffer_init (&buf, 32);
3755 /* Encode calling convention */
3756 /* Change Any to Standard */
3757 if ((helper->call_conv & 0x03) == 0x03)
3758 helper->call_conv = 0x01;
3759 /* explicit_this implies has_this */
3760 if (helper->call_conv & 0x40)
3761 helper->call_conv &= 0x20;
3763 if (helper->call_conv == 0) { /* Unmanaged */
3764 idx = helper->unmanaged_call_conv - 1;
3767 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3768 if (helper->call_conv & 0x02) /* varargs */
3772 sigbuffer_add_byte (&buf, idx);
3773 sigbuffer_add_value (&buf, nargs);
3774 encode_reflection_type (assembly, helper->return_type, &buf, error);
3777 for (i = 0; i < nargs; ++i) {
3778 MonoArray *modreqs = NULL;
3779 MonoArray *modopts = NULL;
3780 MonoReflectionType *pt;
3782 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3783 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3784 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3785 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3787 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3790 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3791 encode_reflection_type (assembly, pt, &buf, error);
3795 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3796 sigbuffer_free (&buf);
3800 sigbuffer_free (&buf);
3805 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3808 MonoDynamicTable *table;
3811 mono_error_init (error);
3813 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3814 idx = table->next_idx ++;
3816 alloc_table (table, table->rows);
3817 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3819 values [MONO_STAND_ALONE_SIGNATURE] =
3820 mono_reflection_encode_sighelper (assembly, helper, error);
3821 return_val_if_nok (error, 0);
3827 reflection_cc_to_file (int call_conv) {
3828 switch (call_conv & 0x3) {
3830 case 1: return MONO_CALL_DEFAULT;
3831 case 2: return MONO_CALL_VARARG;
3833 g_assert_not_reached ();
3837 #endif /* !DISABLE_REFLECTION_EMIT */
3841 MonoMethodSignature *sig;
3846 #ifndef DISABLE_REFLECTION_EMIT
3848 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3853 MonoMethodSignature *sig;
3854 ArrayMethod *am = NULL;
3857 mono_error_init (error);
3859 nparams = mono_array_length (m->parameters);
3860 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3862 sig->sentinelpos = -1;
3863 sig->call_convention = reflection_cc_to_file (m->call_conv);
3864 sig->param_count = nparams;
3866 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3870 sig->ret = &mono_defaults.void_class->byval_arg;
3872 mtype = mono_reflection_type_get_handle (m->parent, error);
3876 for (i = 0; i < nparams; ++i) {
3877 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3882 name = mono_string_to_utf8 (m->name);
3883 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3884 am = (ArrayMethod *)tmp->data;
3885 if (strcmp (name, am->name) == 0 &&
3886 mono_metadata_type_equal (am->parent, mtype) &&
3887 mono_metadata_signature_equal (am->sig, sig)) {
3890 m->table_idx = am->token & 0xffffff;
3894 am = g_new0 (ArrayMethod, 1);
3898 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3899 method_encode_signature (assembly, sig));
3900 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3901 m->table_idx = am->token & 0xffffff;
3912 * Insert into the metadata tables all the info about the TypeBuilder tb.
3913 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3916 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3918 MonoDynamicTable *table;
3920 int i, is_object = 0, is_system = 0;
3923 mono_error_init (error);
3925 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3926 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3927 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3928 n = mono_string_to_utf8 (tb->name);
3929 if (strcmp (n, "Object") == 0)
3931 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3933 n = mono_string_to_utf8 (tb->nspace);
3934 if (strcmp (n, "System") == 0)
3936 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3938 if (tb->parent && !(is_system && is_object) &&
3939 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3940 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3941 return_val_if_nok (error, FALSE);
3942 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3944 values [MONO_TYPEDEF_EXTENDS] = 0;
3946 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3947 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3950 * if we have explicitlayout or sequentiallayouts, output data in the
3951 * ClassLayout table.
3953 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3954 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3955 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3957 alloc_table (table, table->rows);
3958 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3959 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3960 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3961 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3964 /* handle interfaces */
3965 if (tb->interfaces) {
3966 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3968 table->rows += mono_array_length (tb->interfaces);
3969 alloc_table (table, table->rows);
3970 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3971 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3972 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3973 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3974 return_val_if_nok (error, FALSE);
3975 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3976 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3977 values += MONO_INTERFACEIMPL_SIZE;
3983 table = &assembly->tables [MONO_TABLE_FIELD];
3984 table->rows += tb->num_fields;
3985 alloc_table (table, table->rows);
3986 for (i = 0; i < tb->num_fields; ++i) {
3987 mono_image_get_field_info (
3988 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3989 return_val_if_nok (error, FALSE);
3993 /* handle constructors */
3995 table = &assembly->tables [MONO_TABLE_METHOD];
3996 table->rows += mono_array_length (tb->ctors);
3997 alloc_table (table, table->rows);
3998 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3999 if (!mono_image_get_ctor_info (domain,
4000 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4006 /* handle methods */
4008 table = &assembly->tables [MONO_TABLE_METHOD];
4009 table->rows += tb->num_methods;
4010 alloc_table (table, table->rows);
4011 for (i = 0; i < tb->num_methods; ++i) {
4012 if (!mono_image_get_method_info (
4013 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4018 /* Do the same with properties etc.. */
4019 if (tb->events && mono_array_length (tb->events)) {
4020 table = &assembly->tables [MONO_TABLE_EVENT];
4021 table->rows += mono_array_length (tb->events);
4022 alloc_table (table, table->rows);
4023 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4025 alloc_table (table, table->rows);
4026 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4027 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4028 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4029 for (i = 0; i < mono_array_length (tb->events); ++i) {
4030 mono_image_get_event_info (
4031 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4032 return_val_if_nok (error, FALSE);
4035 if (tb->properties && mono_array_length (tb->properties)) {
4036 table = &assembly->tables [MONO_TABLE_PROPERTY];
4037 table->rows += mono_array_length (tb->properties);
4038 alloc_table (table, table->rows);
4039 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4041 alloc_table (table, table->rows);
4042 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4043 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4044 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4045 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4046 mono_image_get_property_info (
4047 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4048 return_val_if_nok (error, FALSE);
4052 /* handle generic parameters */
4053 if (tb->generic_params) {
4054 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4055 table->rows += mono_array_length (tb->generic_params);
4056 alloc_table (table, table->rows);
4057 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4058 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4060 mono_image_get_generic_param_info (
4061 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4065 mono_image_add_decl_security (assembly,
4066 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4069 MonoDynamicTable *ntable;
4071 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4072 ntable->rows += mono_array_length (tb->subtypes);
4073 alloc_table (ntable, ntable->rows);
4074 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4076 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4077 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4079 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4080 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4081 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4082 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4083 mono_string_to_utf8 (tb->name), tb->table_idx,
4084 ntable->next_idx, ntable->rows);*/
4085 values += MONO_NESTED_CLASS_SIZE;
4095 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4099 mono_ptr_array_append (*types, type);
4101 if (!type->subtypes)
4104 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4105 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4106 collect_types (types, subtype);
4111 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4113 if ((*type1)->table_idx < (*type2)->table_idx)
4116 if ((*type1)->table_idx > (*type2)->table_idx)
4123 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4126 mono_error_init (error);
4129 for (i = 0; i < mono_array_length (pinfo); ++i) {
4130 MonoReflectionParamBuilder *pb;
4131 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4134 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4142 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4145 mono_error_init (error);
4147 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4150 for (i = 0; i < tb->num_fields; ++i) {
4151 MonoReflectionFieldBuilder* fb;
4152 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4153 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4158 for (i = 0; i < mono_array_length (tb->events); ++i) {
4159 MonoReflectionEventBuilder* eb;
4160 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4161 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4165 if (tb->properties) {
4166 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4167 MonoReflectionPropertyBuilder* pb;
4168 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4169 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4174 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4175 MonoReflectionCtorBuilder* cb;
4176 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4177 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4178 !params_add_cattrs (assembly, cb->pinfo, error))
4184 for (i = 0; i < tb->num_methods; ++i) {
4185 MonoReflectionMethodBuilder* mb;
4186 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4187 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4188 !params_add_cattrs (assembly, mb->pinfo, error))
4194 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4195 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4204 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4208 mono_error_init (error);
4210 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4213 if (moduleb->global_methods) {
4214 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4215 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4216 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4217 !params_add_cattrs (assembly, mb->pinfo, error))
4222 if (moduleb->global_fields) {
4223 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4224 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4225 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4230 if (moduleb->types) {
4231 for (i = 0; i < moduleb->num_types; ++i) {
4232 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4241 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4243 MonoDynamicTable *table;
4247 char *b = blob_size;
4250 table = &assembly->tables [MONO_TABLE_FILE];
4252 alloc_table (table, table->rows);
4253 values = table->values + table->next_idx * MONO_FILE_SIZE;
4254 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4255 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4256 if (image_is_dynamic (module->image)) {
4257 /* This depends on the fact that the main module is emitted last */
4258 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4259 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4262 path = g_strdup (module->image->name);
4264 mono_sha1_get_digest_from_file (path, hash);
4267 mono_metadata_encode_value (20, b, &b);
4268 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4269 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4274 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4276 MonoDynamicTable *table;
4279 table = &assembly->tables [MONO_TABLE_MODULE];
4280 mb->table_idx = table->next_idx ++;
4281 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4282 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4285 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4286 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4287 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4288 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4292 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4293 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4295 MonoDynamicTable *table;
4299 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4300 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4303 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4305 alloc_table (table, table->rows);
4306 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4308 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4309 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4310 if (klass->nested_in)
4311 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4313 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4314 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4315 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4317 res = table->next_idx;
4321 /* Emit nested types */
4322 if (klass->ext && klass->ext->nested_classes) {
4325 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4326 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4333 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4334 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4340 mono_error_init (error);
4342 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4343 return_if_nok (error);
4345 klass = mono_class_from_mono_type (t);
4347 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4349 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4350 parent_index, assembly);
4354 * We need to do this ourselves since klass->nested_classes is not set up.
4357 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4358 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4359 return_if_nok (error);
4365 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4366 guint32 module_index, MonoDynamicImage *assembly)
4368 MonoImage *image = module->image;
4372 t = &image->tables [MONO_TABLE_TYPEDEF];
4374 for (i = 0; i < t->rows; ++i) {
4376 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4377 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4379 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4380 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4385 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4387 MonoDynamicTable *table;
4389 guint32 scope, scope_idx, impl, current_idx;
4390 gboolean forwarder = TRUE;
4391 gpointer iter = NULL;
4394 if (klass->nested_in) {
4395 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4398 scope = resolution_scope_from_image (assembly, klass->image);
4399 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4400 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4401 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4404 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4407 alloc_table (table, table->rows);
4408 current_idx = table->next_idx;
4409 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4411 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4412 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4413 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4414 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4415 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4419 while ((nested = mono_class_get_nested_types (klass, &iter)))
4420 add_exported_type (assemblyb, assembly, nested, current_idx);
4424 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4430 if (!assemblyb->type_forwarders)
4433 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4434 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4439 type = mono_reflection_type_get_handle (t, &error);
4440 mono_error_assert_ok (&error);
4443 klass = mono_class_from_mono_type (type);
4445 add_exported_type (assemblyb, assembly, klass, 0);
4449 #define align_pointer(base,p)\
4451 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4453 (p) += 4 - (__diff & 3);\
4457 compare_constants (const void *a, const void *b)
4459 const guint32 *a_values = (const guint32 *)a;
4460 const guint32 *b_values = (const guint32 *)b;
4461 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4465 compare_semantics (const void *a, const void *b)
4467 const guint32 *a_values = (const guint32 *)a;
4468 const guint32 *b_values = (const guint32 *)b;
4469 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4472 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4476 compare_custom_attrs (const void *a, const void *b)
4478 const guint32 *a_values = (const guint32 *)a;
4479 const guint32 *b_values = (const guint32 *)b;
4481 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4485 compare_field_marshal (const void *a, const void *b)
4487 const guint32 *a_values = (const guint32 *)a;
4488 const guint32 *b_values = (const guint32 *)b;
4490 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4494 compare_nested (const void *a, const void *b)
4496 const guint32 *a_values = (const guint32 *)a;
4497 const guint32 *b_values = (const guint32 *)b;
4499 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4503 compare_genericparam (const void *a, const void *b)
4506 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4507 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4509 if ((*b_entry)->owner == (*a_entry)->owner) {
4510 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4511 mono_error_assert_ok (&error);
4512 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4513 mono_error_assert_ok (&error);
4515 mono_type_get_generic_param_num (a_type) -
4516 mono_type_get_generic_param_num (b_type);
4518 return (*a_entry)->owner - (*b_entry)->owner;
4522 compare_declsecurity_attrs (const void *a, const void *b)
4524 const guint32 *a_values = (const guint32 *)a;
4525 const guint32 *b_values = (const guint32 *)b;
4527 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4531 compare_interface_impl (const void *a, const void *b)
4533 const guint32 *a_values = (const guint32 *)a;
4534 const guint32 *b_values = (const guint32 *)b;
4536 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4540 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4544 pad_heap (MonoDynamicStream *sh)
4546 if (sh->index & 3) {
4547 int sz = 4 - (sh->index & 3);
4548 memset (sh->data + sh->index, 0, sz);
4555 MonoDynamicStream *stream;
4559 * build_compressed_metadata() fills in the blob of data that represents the
4560 * raw metadata as it will be saved in the PE file. The five streams are output
4561 * and the metadata tables are comnpressed from the guint32 array representation,
4562 * to the compressed on-disk format.
4565 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4567 MonoDynamicTable *table;
4569 guint64 valid_mask = 0;
4570 guint64 sorted_mask;
4571 guint32 heapt_size = 0;
4572 guint32 meta_size = 256; /* allow for header and other stuff */
4573 guint32 table_offset;
4574 guint32 ntables = 0;
4580 struct StreamDesc stream_desc [5];
4582 mono_error_init (error);
4584 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4585 for (i = 0; i < assembly->gen_params->len; i++) {
4586 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4587 if (!write_generic_param_entry (assembly, entry, error))
4591 stream_desc [0].name = "#~";
4592 stream_desc [0].stream = &assembly->tstream;
4593 stream_desc [1].name = "#Strings";
4594 stream_desc [1].stream = &assembly->sheap;
4595 stream_desc [2].name = "#US";
4596 stream_desc [2].stream = &assembly->us;
4597 stream_desc [3].name = "#Blob";
4598 stream_desc [3].stream = &assembly->blob;
4599 stream_desc [4].name = "#GUID";
4600 stream_desc [4].stream = &assembly->guid;
4602 /* tables that are sorted */
4603 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4604 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4605 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4606 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4607 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4608 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4609 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4611 /* Compute table sizes */
4612 /* the MonoImage has already been created in mono_image_basic_init() */
4613 meta = &assembly->image;
4615 /* sizes should be multiple of 4 */
4616 pad_heap (&assembly->blob);
4617 pad_heap (&assembly->guid);
4618 pad_heap (&assembly->sheap);
4619 pad_heap (&assembly->us);
4621 /* Setup the info used by compute_sizes () */
4622 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4623 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4624 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4626 meta_size += assembly->blob.index;
4627 meta_size += assembly->guid.index;
4628 meta_size += assembly->sheap.index;
4629 meta_size += assembly->us.index;
4631 for (i=0; i < MONO_TABLE_NUM; ++i)
4632 meta->tables [i].rows = assembly->tables [i].rows;
4634 for (i = 0; i < MONO_TABLE_NUM; i++){
4635 if (meta->tables [i].rows == 0)
4637 valid_mask |= (guint64)1 << i;
4639 meta->tables [i].row_size = mono_metadata_compute_size (
4640 meta, i, &meta->tables [i].size_bitfield);
4641 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4643 heapt_size += 24; /* #~ header size */
4644 heapt_size += ntables * 4;
4645 /* make multiple of 4 */
4648 meta_size += heapt_size;
4649 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4650 p = (unsigned char*)meta->raw_metadata;
4651 /* the metadata signature */
4652 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4653 /* version numbers and 4 bytes reserved */
4654 int16val = (guint16*)p;
4655 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4656 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4658 /* version string */
4659 int32val = (guint32*)p;
4660 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4662 memcpy (p, meta->version, strlen (meta->version));
4663 p += GUINT32_FROM_LE (*int32val);
4664 align_pointer (meta->raw_metadata, p);
4665 int16val = (guint16*)p;
4666 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4667 *int16val = GUINT16_TO_LE (5); /* number of streams */
4671 * write the stream info.
4673 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4674 table_offset += 3; table_offset &= ~3;
4676 assembly->tstream.index = heapt_size;
4677 for (i = 0; i < 5; ++i) {
4678 int32val = (guint32*)p;
4679 stream_desc [i].stream->offset = table_offset;
4680 *int32val++ = GUINT32_TO_LE (table_offset);
4681 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4682 table_offset += GUINT32_FROM_LE (*int32val);
4683 table_offset += 3; table_offset &= ~3;
4685 strcpy ((char*)p, stream_desc [i].name);
4686 p += strlen (stream_desc [i].name) + 1;
4687 align_pointer (meta->raw_metadata, p);
4690 * now copy the data, the table stream header and contents goes first.
4692 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4693 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4694 int32val = (guint32*)p;
4695 *int32val = GUINT32_TO_LE (0); /* reserved */
4698 *p++ = 2; /* version */
4701 if (meta->idx_string_wide)
4703 if (meta->idx_guid_wide)
4705 if (meta->idx_blob_wide)
4708 *p++ = 1; /* reserved */
4709 int64val = (guint64*)p;
4710 *int64val++ = GUINT64_TO_LE (valid_mask);
4711 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4713 int32val = (guint32*)p;
4714 for (i = 0; i < MONO_TABLE_NUM; i++){
4715 if (meta->tables [i].rows == 0)
4717 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4719 p = (unsigned char*)int32val;
4721 /* sort the tables that still need sorting */
4722 table = &assembly->tables [MONO_TABLE_CONSTANT];
4724 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4725 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4727 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4728 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4730 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4731 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4733 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4734 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4736 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4737 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4738 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4740 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4741 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4743 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4745 /* compress the tables */
4746 for (i = 0; i < MONO_TABLE_NUM; i++){
4749 guint32 bitfield = meta->tables [i].size_bitfield;
4750 if (!meta->tables [i].rows)
4752 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4753 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4754 meta->tables [i].base = (char*)p;
4755 for (row = 1; row <= meta->tables [i].rows; ++row) {
4756 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4757 for (col = 0; col < assembly->tables [i].columns; ++col) {
4758 switch (mono_metadata_table_size (bitfield, col)) {
4760 *p++ = values [col];
4763 *p++ = values [col] & 0xff;
4764 *p++ = (values [col] >> 8) & 0xff;
4767 *p++ = values [col] & 0xff;
4768 *p++ = (values [col] >> 8) & 0xff;
4769 *p++ = (values [col] >> 16) & 0xff;
4770 *p++ = (values [col] >> 24) & 0xff;
4773 g_assert_not_reached ();
4777 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4780 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4781 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4782 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4783 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4784 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4786 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4792 * Some tables in metadata need to be sorted according to some criteria, but
4793 * when methods and fields are first created with reflection, they may be assigned a token
4794 * that doesn't correspond to the final token they will get assigned after the sorting.
4795 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4796 * with the reflection objects that represent them. Once all the tables are set up, the
4797 * reflection objects will contains the correct table index. fixup_method() will fixup the
4798 * tokens for the method with ILGenerator @ilgen.
4801 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4803 guint32 code_idx = GPOINTER_TO_UINT (value);
4804 MonoReflectionILTokenInfo *iltoken;
4805 MonoReflectionFieldBuilder *field;
4806 MonoReflectionCtorBuilder *ctor;
4807 MonoReflectionMethodBuilder *method;
4808 MonoReflectionTypeBuilder *tb;
4809 MonoReflectionArrayMethod *am;
4811 unsigned char *target;
4813 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4814 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4815 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4816 switch (target [3]) {
4817 case MONO_TABLE_FIELD:
4818 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4819 field = (MonoReflectionFieldBuilder *)iltoken->member;
4820 idx = field->table_idx;
4821 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4822 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4823 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4825 g_assert_not_reached ();
4828 case MONO_TABLE_METHOD:
4829 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4830 method = (MonoReflectionMethodBuilder *)iltoken->member;
4831 idx = method->table_idx;
4832 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4833 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4834 idx = ctor->table_idx;
4835 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4836 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4837 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4838 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4840 g_assert_not_reached ();
4843 case MONO_TABLE_TYPEDEF:
4844 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4845 g_assert_not_reached ();
4846 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4847 idx = tb->table_idx;
4849 case MONO_TABLE_MEMBERREF:
4850 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4851 am = (MonoReflectionArrayMethod*)iltoken->member;
4852 idx = am->table_idx;
4853 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4854 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4855 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4856 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4857 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4858 g_assert (m->klass->generic_class || m->klass->generic_container);
4860 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4862 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4863 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4864 g_assert (is_field_on_inst (f));
4866 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4867 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4869 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4871 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4873 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4876 g_assert_not_reached ();
4879 case MONO_TABLE_METHODSPEC:
4880 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4881 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4882 g_assert (mono_method_signature (m)->generic_param_count);
4884 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4886 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4889 g_assert_not_reached ();
4893 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4895 target [0] = idx & 0xff;
4896 target [1] = (idx >> 8) & 0xff;
4897 target [2] = (idx >> 16) & 0xff;
4904 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4905 * value is not known when the table is emitted.
4908 fixup_cattrs (MonoDynamicImage *assembly)
4910 MonoDynamicTable *table;
4912 guint32 type, i, idx, token;
4915 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4917 for (i = 0; i < table->rows; ++i) {
4918 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4920 type = values [MONO_CUSTOM_ATTR_TYPE];
4921 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4922 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4923 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4924 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4927 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4928 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4929 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4930 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4931 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4932 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4933 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4934 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4941 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4943 MonoDynamicTable *table;
4946 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4948 alloc_table (table, table->rows);
4949 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4950 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4951 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4952 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4953 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4958 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4960 MonoDynamicTable *table;
4964 char *b = blob_size;
4966 guint32 idx, offset;
4968 if (rsrc->filename) {
4969 name = mono_string_to_utf8 (rsrc->filename);
4970 sname = g_path_get_basename (name);
4972 table = &assembly->tables [MONO_TABLE_FILE];
4974 alloc_table (table, table->rows);
4975 values = table->values + table->next_idx * MONO_FILE_SIZE;
4976 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4977 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4980 mono_sha1_get_digest_from_file (name, hash);
4981 mono_metadata_encode_value (20, b, &b);
4982 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4983 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4985 idx = table->next_idx++;
4987 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4993 data = mono_array_addr (rsrc->data, char, 0);
4994 len = mono_array_length (rsrc->data);
5000 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5001 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5002 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5003 mono_image_add_stream_data (&assembly->resources, data, len);
5007 * The entry should be emitted into the MANIFESTRESOURCE table of
5008 * the main module, but that needs to reference the FILE table
5009 * which isn't emitted yet.
5016 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5020 set_version_from_string (MonoString *version, guint32 *values)
5022 gchar *ver, *p, *str;
5025 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5026 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5027 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5028 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5031 ver = str = mono_string_to_utf8 (version);
5032 for (i = 0; i < 4; ++i) {
5033 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5039 /* handle Revision and Build */
5049 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5053 char *b = blob_size;
5058 len = mono_array_length (pkey);
5059 mono_metadata_encode_value (len, b, &b);
5060 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5061 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5063 assembly->public_key = (guint8 *)g_malloc (len);
5064 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5065 assembly->public_key_len = len;
5067 /* Special case: check for ECMA key (16 bytes) */
5068 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5069 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5070 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5071 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5072 /* minimum key size (in 2.0) is 384 bits */
5073 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5075 /* FIXME - verifier */
5076 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5077 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5079 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5085 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5087 MonoDynamicTable *table;
5088 MonoDynamicImage *assembly;
5089 MonoReflectionAssemblyBuilder *assemblyb;
5093 guint32 module_index;
5095 mono_error_init (error);
5097 assemblyb = moduleb->assemblyb;
5098 assembly = moduleb->dynamic_image;
5099 domain = mono_object_domain (assemblyb);
5101 /* Emit ASSEMBLY table */
5102 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5103 alloc_table (table, 1);
5104 values = table->values + MONO_ASSEMBLY_SIZE;
5105 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5106 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5107 if (assemblyb->culture) {
5108 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5110 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5112 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5113 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5114 set_version_from_string (assemblyb->version, values);
5116 /* Emit FILE + EXPORTED_TYPE table */
5118 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5120 MonoReflectionModuleBuilder *file_module =
5121 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5122 if (file_module != moduleb) {
5123 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5125 if (file_module->types) {
5126 for (j = 0; j < file_module->num_types; ++j) {
5127 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5128 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5129 return_if_nok (error);
5134 if (assemblyb->loaded_modules) {
5135 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5136 MonoReflectionModule *file_module =
5137 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5138 mono_image_fill_file_table (domain, file_module, assembly);
5140 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5143 if (assemblyb->type_forwarders)
5144 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5146 /* Emit MANIFESTRESOURCE table */
5148 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5150 MonoReflectionModuleBuilder *file_module =
5151 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5152 /* The table for the main module is emitted later */
5153 if (file_module != moduleb) {
5155 if (file_module->resources) {
5156 int len = mono_array_length (file_module->resources);
5157 for (j = 0; j < len; ++j) {
5158 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5159 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5166 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5169 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5170 * for the modulebuilder @moduleb.
5171 * At the end of the process, method and field tokens are fixed up and the
5172 * on-disk compressed metadata representation is created.
5173 * Return TRUE on success, or FALSE on failure and sets @error
5176 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5178 MonoDynamicTable *table;
5179 MonoDynamicImage *assembly;
5180 MonoReflectionAssemblyBuilder *assemblyb;
5186 mono_error_init (error);
5188 assemblyb = moduleb->assemblyb;
5189 assembly = moduleb->dynamic_image;
5190 domain = mono_object_domain (assemblyb);
5192 if (assembly->text_rva)
5195 assembly->text_rva = START_TEXT_RVA;
5197 if (moduleb->is_main) {
5198 mono_image_emit_manifest (moduleb, error);
5199 return_val_if_nok (error, FALSE);
5202 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5203 table->rows = 1; /* .<Module> */
5205 alloc_table (table, table->rows);
5207 * Set the first entry.
5209 values = table->values + table->columns;
5210 values [MONO_TYPEDEF_FLAGS] = 0;
5211 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5212 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5213 values [MONO_TYPEDEF_EXTENDS] = 0;
5214 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5215 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5218 * handle global methods
5219 * FIXME: test what to do when global methods are defined in multiple modules.
5221 if (moduleb->global_methods) {
5222 table = &assembly->tables [MONO_TABLE_METHOD];
5223 table->rows += mono_array_length (moduleb->global_methods);
5224 alloc_table (table, table->rows);
5225 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5226 if (!mono_image_get_method_info (
5227 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5231 if (moduleb->global_fields) {
5232 table = &assembly->tables [MONO_TABLE_FIELD];
5233 table->rows += mono_array_length (moduleb->global_fields);
5234 alloc_table (table, table->rows);
5235 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5236 mono_image_get_field_info (
5237 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5244 table = &assembly->tables [MONO_TABLE_MODULE];
5245 alloc_table (table, 1);
5246 mono_image_fill_module_table (domain, moduleb, assembly);
5248 /* Collect all types into a list sorted by their table_idx */
5249 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5252 for (i = 0; i < moduleb->num_types; ++i) {
5253 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5254 collect_types (&types, type);
5257 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5258 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5259 table->rows += mono_ptr_array_size (types);
5260 alloc_table (table, table->rows);
5263 * Emit type names + namespaces at one place inside the string heap,
5264 * so load_class_names () needs to touch fewer pages.
5266 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5267 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5268 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5270 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5271 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5272 string_heap_insert_mstring (&assembly->sheap, tb->name);
5275 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5276 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5277 if (!mono_image_get_type_info (domain, type, assembly, error))
5282 * table->rows is already set above and in mono_image_fill_module_table.
5284 /* add all the custom attributes at the end, once all the indexes are stable */
5285 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5288 /* CAS assembly permissions */
5289 if (assemblyb->permissions_minimum)
5290 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5291 if (assemblyb->permissions_optional)
5292 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5293 if (assemblyb->permissions_refused)
5294 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5296 if (!module_add_cattrs (assembly, moduleb, error))
5300 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5302 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5303 * the final tokens and don't need another fixup pass. */
5305 if (moduleb->global_methods) {
5306 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5307 MonoReflectionMethodBuilder *mb = mono_array_get (
5308 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5309 if (!mono_image_add_methodimpl (assembly, mb, error))
5314 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5315 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5316 if (type->methods) {
5317 for (j = 0; j < type->num_methods; ++j) {
5318 MonoReflectionMethodBuilder *mb = mono_array_get (
5319 type->methods, MonoReflectionMethodBuilder*, j);
5321 if (!mono_image_add_methodimpl (assembly, mb, error))
5327 fixup_cattrs (assembly);
5330 mono_ptr_array_destroy (types);
5333 return mono_error_ok (error);
5336 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5339 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5341 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5344 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5348 guint32 import_lookup_table;
5352 guint32 import_address_table_rva;
5360 #ifndef DISABLE_REFLECTION_EMIT
5363 * mono_image_insert_string:
5364 * @module: module builder object
5367 * Insert @str into the user string stream of @module.
5370 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5372 MonoDynamicImage *assembly;
5377 if (!module->dynamic_image)
5378 mono_image_module_basic_init (module);
5380 assembly = module->dynamic_image;
5382 if (assembly->save) {
5383 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5384 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5385 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5387 char *swapped = g_malloc (2 * mono_string_length (str));
5388 const char *p = (const char*)mono_string_chars (str);
5390 swap_with_size (swapped, p, 2, mono_string_length (str));
5391 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5395 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5397 mono_image_add_stream_data (&assembly->us, "", 1);
5399 idx = assembly->us.index ++;
5402 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5404 return MONO_TOKEN_STRING | idx;
5408 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5412 MonoMethodSignature *sig;
5414 mono_error_init (error);
5416 klass = obj->vtable->klass;
5417 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5418 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5419 MonoMethodSignature *old;
5420 guint32 sig_token, parent;
5423 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5425 nargs = mono_array_length (opt_param_types);
5426 old = mono_method_signature (method);
5427 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5429 sig->hasthis = old->hasthis;
5430 sig->explicit_this = old->explicit_this;
5431 sig->call_convention = old->call_convention;
5432 sig->generic_param_count = old->generic_param_count;
5433 sig->param_count = old->param_count + nargs;
5434 sig->sentinelpos = old->param_count;
5435 sig->ret = old->ret;
5437 for (i = 0; i < old->param_count; i++)
5438 sig->params [i] = old->params [i];
5440 for (i = 0; i < nargs; i++) {
5441 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5442 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5443 if (!is_ok (error)) goto fail;
5446 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5447 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5448 parent >>= MONO_TYPEDEFORREF_BITS;
5450 parent <<= MONO_MEMBERREF_PARENT_BITS;
5451 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5453 sig_token = method_encode_signature (assembly, sig);
5454 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5455 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5456 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5457 ReflectionMethodBuilder rmb;
5458 guint32 parent, sig_token;
5459 int nopt_args, nparams, ngparams, i;
5461 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5464 rmb.opt_types = opt_param_types;
5465 nopt_args = mono_array_length (opt_param_types);
5467 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5468 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5469 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5471 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5472 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5473 sig->call_convention = rmb.call_conv;
5474 sig->generic_param_count = ngparams;
5475 sig->param_count = nparams + nopt_args;
5476 sig->sentinelpos = nparams;
5477 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5478 if (!is_ok (error)) goto fail;
5480 for (i = 0; i < nparams; i++) {
5481 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5482 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5483 if (!is_ok (error)) goto fail;
5486 for (i = 0; i < nopt_args; i++) {
5487 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5488 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5489 if (!is_ok (error)) goto fail;
5492 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5496 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5497 if (!mono_error_ok (error))
5499 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5501 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5502 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5504 char *name = mono_string_to_utf8 (rmb.name);
5505 token = mono_image_get_varargs_method_token (
5506 assembly, parent, name, sig_token);
5509 g_error ("requested method token for %s\n", klass->name);
5512 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5513 register_dyn_token (assembly, token, obj);
5516 g_assert (!mono_error_ok (error));
5521 * mono_image_create_token:
5522 * @assembly: a dynamic assembly
5524 * @register_token: Whenever to register the token in the assembly->tokens hash.
5526 * Get a token to insert in the IL code stream for the given MemberInfo.
5527 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5528 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5532 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5533 gboolean create_open_instance, gboolean register_token,
5539 mono_error_init (error);
5541 klass = obj->vtable->klass;
5543 /* Check for user defined reflection objects */
5544 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5545 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5546 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5550 if (strcmp (klass->name, "MethodBuilder") == 0) {
5551 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5552 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5554 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5555 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5557 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5558 if (!mono_error_ok (error))
5561 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5562 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5563 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5564 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5566 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5567 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5569 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5570 if (!mono_error_ok (error))
5573 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5574 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5575 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5576 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5577 if (tb->generic_params) {
5578 token = mono_image_get_generic_field_token (assembly, fb, error);
5579 return_val_if_nok (error, 0);
5581 if (tb->module->dynamic_image == assembly) {
5582 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5584 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5587 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5588 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5589 if (create_open_instance && tb->generic_params) {
5591 init_type_builder_generics (obj, error);
5592 return_val_if_nok (error, 0);
5593 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594 return_val_if_nok (error, 0);
5595 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5596 token = mono_metadata_token_from_dor (token);
5597 } else if (tb->module->dynamic_image == assembly) {
5598 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5601 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5602 return_val_if_nok (error, 0);
5603 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5605 } else if (strcmp (klass->name, "MonoType") == 0) {
5606 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5607 return_val_if_nok (error, 0);
5608 MonoClass *mc = mono_class_from_mono_type (type);
5609 token = mono_metadata_token_from_dor (
5610 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5611 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5612 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5613 return_val_if_nok (error, 0);
5614 token = mono_metadata_token_from_dor (
5615 mono_image_typedef_or_ref (assembly, type));
5616 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5617 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5618 return_val_if_nok (error, 0);
5619 token = mono_metadata_token_from_dor (
5620 mono_image_typedef_or_ref (assembly, type));
5621 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5622 strcmp (klass->name, "MonoMethod") == 0 ||
5623 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5624 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5625 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5626 if (m->method->is_inflated) {
5627 if (create_open_instance)
5628 token = mono_image_get_methodspec_token (assembly, m->method);
5630 token = mono_image_get_inflated_method_token (assembly, m->method);
5631 } else if ((m->method->klass->image == &assembly->image) &&
5632 !m->method->klass->generic_class) {
5633 static guint32 method_table_idx = 0xffffff;
5634 if (m->method->klass->wastypebuilder) {
5635 /* we use the same token as the one that was assigned
5636 * to the Methodbuilder.
5637 * FIXME: do the equivalent for Fields.
5639 token = m->method->token;
5642 * Each token should have a unique index, but the indexes are
5643 * assigned by managed code, so we don't know about them. An
5644 * easy solution is to count backwards...
5646 method_table_idx --;
5647 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5650 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5652 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5653 } else if (strcmp (klass->name, "MonoField") == 0) {
5654 MonoReflectionField *f = (MonoReflectionField *)obj;
5655 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5656 static guint32 field_table_idx = 0xffffff;
5658 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5660 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5662 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5663 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5664 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5665 token = mono_image_get_array_token (assembly, m, error);
5666 return_val_if_nok (error, 0);
5667 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5668 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5669 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5670 return_val_if_nok (error, 0);
5671 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5672 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5673 return_val_if_nok (error, 0);
5674 token = mono_metadata_token_from_dor (
5675 mono_image_typedef_or_ref (assembly, type));
5676 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5677 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5678 token = mono_image_get_field_on_inst_token (assembly, f, error);
5679 return_val_if_nok (error, 0);
5680 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5681 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5682 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5683 if (!mono_error_ok (error))
5685 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5686 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5687 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5688 if (!mono_error_ok (error))
5690 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5691 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5692 return_val_if_nok (error, 0);
5693 token = mono_metadata_token_from_dor (
5694 mono_image_typedef_or_ref (assembly, type));
5696 g_error ("requested token for %s\n", klass->name);
5700 mono_image_register_token (assembly, token, obj);
5706 * mono_image_register_token:
5708 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5709 * the Module.ResolveXXXToken () methods to work.
5712 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5716 dynamic_image_lock (assembly);
5717 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5719 /* There could be multiple MethodInfo objects with the same token */
5720 //g_assert (prev == obj);
5722 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5724 dynamic_image_unlock (assembly);
5727 static MonoDynamicImage*
5728 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5730 static const guchar entrycode [16] = {0xff, 0x25, 0};
5731 MonoDynamicImage *image;
5734 const char *version;
5736 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5737 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5739 version = mono_get_runtime_info ()->runtime_version;
5742 /* The MonoGHashTable's need GC tracking */
5743 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5745 image = g_new0 (MonoDynamicImage, 1);
5748 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5750 /*g_print ("created image %p\n", image);*/
5751 /* keep in sync with image.c */
5752 image->image.name = assembly_name;
5753 image->image.assembly_name = image->image.name; /* they may be different */
5754 image->image.module_name = module_name;
5755 image->image.version = g_strdup (version);
5756 image->image.md_version_major = 1;
5757 image->image.md_version_minor = 1;
5758 image->image.dynamic = TRUE;
5760 image->image.references = g_new0 (MonoAssembly*, 1);
5761 image->image.references [0] = NULL;
5763 mono_image_init (&image->image);
5765 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5766 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5767 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5768 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5769 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5770 image->handleref = g_hash_table_new (NULL, NULL);
5771 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5772 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5773 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5774 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5775 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5776 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5777 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5778 image->gen_params = g_ptr_array_new ();
5779 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5781 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5782 string_heap_init (&image->sheap);
5783 mono_image_add_stream_data (&image->us, "", 1);
5784 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5785 /* import tables... */
5786 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5787 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5788 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5789 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5790 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5791 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5792 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5793 stream_data_align (&image->code);
5795 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5797 for (i=0; i < MONO_TABLE_NUM; ++i) {
5798 image->tables [i].next_idx = 1;
5799 image->tables [i].columns = table_sizes [i];
5802 image->image.assembly = (MonoAssembly*)assembly;
5803 image->run = assembly->run;
5804 image->save = assembly->save;
5805 image->pe_kind = 0x1; /* ILOnly */
5806 image->machine = 0x14c; /* I386 */
5808 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5810 dynamic_images_lock ();
5812 if (!dynamic_images)
5813 dynamic_images = g_ptr_array_new ();
5815 g_ptr_array_add (dynamic_images, image);
5817 dynamic_images_unlock ();
5824 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5830 release_hashtable (MonoGHashTable **hash)
5833 mono_g_hash_table_destroy (*hash);
5839 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5841 release_hashtable (&image->token_fixups);
5842 release_hashtable (&image->handleref_managed);
5843 release_hashtable (&image->tokens);
5844 release_hashtable (&image->remapped_tokens);
5845 release_hashtable (&image->generic_def_objects);
5846 release_hashtable (&image->methodspec);
5849 // Free dynamic image pass one: Free resources but not image itself
5851 mono_dynamic_image_free (MonoDynamicImage *image)
5853 MonoDynamicImage *di = image;
5858 mono_g_hash_table_destroy (di->methodspec);
5860 g_hash_table_destroy (di->typespec);
5862 g_hash_table_destroy (di->typeref);
5864 g_hash_table_destroy (di->handleref);
5865 if (di->handleref_managed)
5866 mono_g_hash_table_destroy (di->handleref_managed);
5868 mono_g_hash_table_destroy (di->tokens);
5869 if (di->remapped_tokens)
5870 mono_g_hash_table_destroy (di->remapped_tokens);
5871 if (di->generic_def_objects)
5872 mono_g_hash_table_destroy (di->generic_def_objects);
5873 if (di->blob_cache) {
5874 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5875 g_hash_table_destroy (di->blob_cache);
5877 if (di->standalonesig_cache)
5878 g_hash_table_destroy (di->standalonesig_cache);
5879 for (list = di->array_methods; list; list = list->next) {
5880 ArrayMethod *am = (ArrayMethod *)list->data;
5885 g_list_free (di->array_methods);
5886 if (di->gen_params) {
5887 for (i = 0; i < di->gen_params->len; i++) {
5888 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5889 mono_gc_deregister_root ((char*) &entry->gparam);
5892 g_ptr_array_free (di->gen_params, TRUE);
5894 if (di->token_fixups)
5895 mono_g_hash_table_destroy (di->token_fixups);
5896 if (di->method_to_table_idx)
5897 g_hash_table_destroy (di->method_to_table_idx);
5898 if (di->field_to_table_idx)
5899 g_hash_table_destroy (di->field_to_table_idx);
5900 if (di->method_aux_hash)
5901 g_hash_table_destroy (di->method_aux_hash);
5902 if (di->vararg_aux_hash)
5903 g_hash_table_destroy (di->vararg_aux_hash);
5904 g_free (di->strong_name);
5905 g_free (di->win32_res);
5907 g_free (di->public_key);
5909 /*g_print ("string heap destroy for image %p\n", di);*/
5910 mono_dynamic_stream_reset (&di->sheap);
5911 mono_dynamic_stream_reset (&di->code);
5912 mono_dynamic_stream_reset (&di->resources);
5913 mono_dynamic_stream_reset (&di->us);
5914 mono_dynamic_stream_reset (&di->blob);
5915 mono_dynamic_stream_reset (&di->tstream);
5916 mono_dynamic_stream_reset (&di->guid);
5917 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5918 g_free (di->tables [i].values);
5921 dynamic_images_lock ();
5924 g_ptr_array_remove (dynamic_images, di);
5926 dynamic_images_unlock ();
5929 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5931 mono_dynamic_image_free_image (MonoDynamicImage *image)
5933 /* See create_dynamic_mono_image () */
5935 /* Allocated using GC_MALLOC */
5941 #ifndef DISABLE_REFLECTION_EMIT
5944 * mono_image_basic_init:
5945 * @assembly: an assembly builder object
5947 * Create the MonoImage that represents the assembly builder and setup some
5948 * of the helper hash table and the basic metadata streams.
5951 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5953 MonoDynamicAssembly *assembly;
5954 MonoDynamicImage *image;
5955 MonoDomain *domain = mono_object_domain (assemblyb);
5957 if (assemblyb->dynamic_assembly)
5961 /* assembly->assembly.image might be GC allocated */
5962 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5964 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5967 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5969 assembly->assembly.ref_count = 1;
5970 assembly->assembly.dynamic = TRUE;
5971 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5972 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5973 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5974 if (assemblyb->culture)
5975 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5977 assembly->assembly.aname.culture = g_strdup ("");
5979 if (assemblyb->version) {
5980 char *vstr = mono_string_to_utf8 (assemblyb->version);
5981 char **version = g_strsplit (vstr, ".", 4);
5982 char **parts = version;
5983 assembly->assembly.aname.major = atoi (*parts++);
5984 assembly->assembly.aname.minor = atoi (*parts++);
5985 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5986 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5988 g_strfreev (version);
5991 assembly->assembly.aname.major = 0;
5992 assembly->assembly.aname.minor = 0;
5993 assembly->assembly.aname.build = 0;
5994 assembly->assembly.aname.revision = 0;
5997 assembly->run = assemblyb->access != 2;
5998 assembly->save = assemblyb->access != 1;
5999 assembly->domain = domain;
6001 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
6002 image->initial_image = TRUE;
6003 assembly->assembly.aname.name = image->image.name;
6004 assembly->assembly.image = &image->image;
6005 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6006 /* -1 to correct for the trailing NULL byte */
6007 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6008 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6010 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6013 mono_domain_assemblies_lock (domain);
6014 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6015 mono_domain_assemblies_unlock (domain);
6017 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6019 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6021 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6024 #endif /* !DISABLE_REFLECTION_EMIT */
6026 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6029 calc_section_size (MonoDynamicImage *assembly)
6033 /* alignment constraints */
6034 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6035 g_assert ((assembly->code.index % 4) == 0);
6036 assembly->meta_size += 3;
6037 assembly->meta_size &= ~3;
6038 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6039 g_assert ((assembly->resources.index % 4) == 0);
6041 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6042 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6045 if (assembly->win32_res) {
6046 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6048 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6049 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6053 assembly->sections [MONO_SECTION_RELOC].size = 12;
6054 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6064 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6068 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6070 ResTreeNode *t1 = (ResTreeNode*)a;
6071 ResTreeNode *t2 = (ResTreeNode*)b;
6073 return t1->id - t2->id;
6077 * resource_tree_create:
6079 * Organize the resources into a resource tree.
6081 static ResTreeNode *
6082 resource_tree_create (MonoArray *win32_resources)
6084 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6088 tree = g_new0 (ResTreeNode, 1);
6090 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6091 MonoReflectionWin32Resource *win32_res =
6092 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6096 /* FIXME: BUG: this stores managed references in unmanaged memory */
6097 lang_node = g_new0 (ResTreeNode, 1);
6098 lang_node->id = win32_res->lang_id;
6099 lang_node->win32_res = win32_res;
6101 /* Create type node if neccesary */
6103 for (l = tree->children; l; l = l->next)
6104 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6105 type_node = (ResTreeNode*)l->data;
6110 type_node = g_new0 (ResTreeNode, 1);
6111 type_node->id = win32_res->res_type;
6114 * The resource types have to be sorted otherwise
6115 * Windows Explorer can't display the version information.
6117 tree->children = g_slist_insert_sorted (tree->children,
6118 type_node, resource_tree_compare_by_id);
6121 /* Create res node if neccesary */
6123 for (l = type_node->children; l; l = l->next)
6124 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6125 res_node = (ResTreeNode*)l->data;
6130 res_node = g_new0 (ResTreeNode, 1);
6131 res_node->id = win32_res->res_id;
6132 type_node->children = g_slist_append (type_node->children, res_node);
6135 res_node->children = g_slist_append (res_node->children, lang_node);
6142 * resource_tree_encode:
6144 * Encode the resource tree into the format used in the PE file.
6147 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6150 MonoPEResourceDir dir;
6151 MonoPEResourceDirEntry dir_entry;
6152 MonoPEResourceDataEntry data_entry;
6154 guint32 res_id_entries;
6157 * For the format of the resource directory, see the article
6158 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6162 memset (&dir, 0, sizeof (dir));
6163 memset (&dir_entry, 0, sizeof (dir_entry));
6164 memset (&data_entry, 0, sizeof (data_entry));
6166 g_assert (sizeof (dir) == 16);
6167 g_assert (sizeof (dir_entry) == 8);
6168 g_assert (sizeof (data_entry) == 16);
6170 node->offset = p - begin;
6172 /* IMAGE_RESOURCE_DIRECTORY */
6173 res_id_entries = g_slist_length (node->children);
6174 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6176 memcpy (p, &dir, sizeof (dir));
6179 /* Reserve space for entries */
6181 p += sizeof (dir_entry) * res_id_entries;
6183 /* Write children */
6184 for (l = node->children; l; l = l->next) {
6185 ResTreeNode *child = (ResTreeNode*)l->data;
6187 if (child->win32_res) {
6190 child->offset = p - begin;
6192 /* IMAGE_RESOURCE_DATA_ENTRY */
6193 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6194 size = mono_array_length (child->win32_res->res_data);
6195 data_entry.rde_size = GUINT32_TO_LE (size);
6197 memcpy (p, &data_entry, sizeof (data_entry));
6198 p += sizeof (data_entry);
6200 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6203 resource_tree_encode (child, begin, p, &p);
6207 /* IMAGE_RESOURCE_ENTRY */
6208 for (l = node->children; l; l = l->next) {
6209 ResTreeNode *child = (ResTreeNode*)l->data;
6211 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6212 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6214 memcpy (entries, &dir_entry, sizeof (dir_entry));
6215 entries += sizeof (dir_entry);
6222 resource_tree_free (ResTreeNode * node)
6225 for (list = node->children; list; list = list->next)
6226 resource_tree_free ((ResTreeNode*)list->data);
6227 g_slist_free(node->children);
6232 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6237 MonoReflectionWin32Resource *win32_res;
6240 if (!assemblyb->win32_resources)
6244 * Resources are stored in a three level tree inside the PE file.
6245 * - level one contains a node for each type of resource
6246 * - level two contains a node for each resource
6247 * - level three contains a node for each instance of a resource for a
6248 * specific language.
6251 tree = resource_tree_create (assemblyb->win32_resources);
6253 /* Estimate the size of the encoded tree */
6255 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6256 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6257 size += mono_array_length (win32_res->res_data);
6259 /* Directory structure */
6260 size += mono_array_length (assemblyb->win32_resources) * 256;
6261 p = buf = (char *)g_malloc (size);
6263 resource_tree_encode (tree, p, p, &p);
6265 g_assert (p - buf <= size);
6267 assembly->win32_res = (char *)g_malloc (p - buf);
6268 assembly->win32_res_size = p - buf;
6269 memcpy (assembly->win32_res, buf, p - buf);
6272 resource_tree_free (tree);
6276 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6278 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6281 p += sizeof (MonoPEResourceDir);
6282 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6283 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6284 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6285 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6286 fixup_resource_directory (res_section, child, rva);
6288 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6289 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6292 p += sizeof (MonoPEResourceDirEntry);
6297 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6300 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6301 g_error ("WriteFile returned %d\n", GetLastError ());
6305 * mono_image_create_pefile:
6306 * @mb: a module builder object
6308 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6309 * assembly->pefile where it can be easily retrieved later in chunks.
6312 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6314 MonoMSDOSHeader *msdos;
6315 MonoDotNetHeader *header;
6316 MonoSectionTable *section;
6317 MonoCLIHeader *cli_header;
6318 guint32 size, image_size, virtual_base, text_offset;
6319 guint32 header_start, section_start, file_offset, virtual_offset;
6320 MonoDynamicImage *assembly;
6321 MonoReflectionAssemblyBuilder *assemblyb;
6322 MonoDynamicStream pefile_stream = {0};
6323 MonoDynamicStream *pefile = &pefile_stream;
6325 guint32 *rva, value;
6327 static const unsigned char msheader[] = {
6328 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6329 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6332 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6333 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6334 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6335 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6338 mono_error_init (error);
6340 assemblyb = mb->assemblyb;
6342 mono_image_basic_init (assemblyb);
6343 assembly = mb->dynamic_image;
6345 assembly->pe_kind = assemblyb->pe_kind;
6346 assembly->machine = assemblyb->machine;
6347 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6348 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6350 if (!mono_image_build_metadata (mb, error))
6354 if (mb->is_main && assemblyb->resources) {
6355 int len = mono_array_length (assemblyb->resources);
6356 for (i = 0; i < len; ++i)
6357 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6360 if (mb->resources) {
6361 int len = mono_array_length (mb->resources);
6362 for (i = 0; i < len; ++i)
6363 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6366 if (!build_compressed_metadata (assembly, error))
6370 assembly_add_win32_resources (assembly, assemblyb);
6372 nsections = calc_section_size (assembly);
6374 /* The DOS header and stub */
6375 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6376 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6378 /* the dotnet header */
6379 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6381 /* the section tables */
6382 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6384 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6385 virtual_offset = VIRT_ALIGN;
6388 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6389 if (!assembly->sections [i].size)
6392 file_offset += FILE_ALIGN - 1;
6393 file_offset &= ~(FILE_ALIGN - 1);
6394 virtual_offset += VIRT_ALIGN - 1;
6395 virtual_offset &= ~(VIRT_ALIGN - 1);
6397 assembly->sections [i].offset = file_offset;
6398 assembly->sections [i].rva = virtual_offset;
6400 file_offset += assembly->sections [i].size;
6401 virtual_offset += assembly->sections [i].size;
6402 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6405 file_offset += FILE_ALIGN - 1;
6406 file_offset &= ~(FILE_ALIGN - 1);
6408 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6410 /* back-patch info */
6411 msdos = (MonoMSDOSHeader*)pefile->data;
6412 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6414 header = (MonoDotNetHeader*)(pefile->data + header_start);
6415 header->pesig [0] = 'P';
6416 header->pesig [1] = 'E';
6418 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6419 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6420 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6421 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6422 if (assemblyb->pekind == 1) {
6424 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6427 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6430 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6432 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6433 header->pe.pe_major = 6;
6434 header->pe.pe_minor = 0;
6435 size = assembly->sections [MONO_SECTION_TEXT].size;
6436 size += FILE_ALIGN - 1;
6437 size &= ~(FILE_ALIGN - 1);
6438 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6439 size = assembly->sections [MONO_SECTION_RSRC].size;
6440 size += FILE_ALIGN - 1;
6441 size &= ~(FILE_ALIGN - 1);
6442 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6443 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6444 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6445 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6446 /* pe_rva_entry_point always at the beginning of the text section */
6447 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6449 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6450 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6451 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6452 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6453 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6454 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6455 size = section_start;
6456 size += FILE_ALIGN - 1;
6457 size &= ~(FILE_ALIGN - 1);
6458 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6460 size += VIRT_ALIGN - 1;
6461 size &= ~(VIRT_ALIGN - 1);
6462 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6465 // Translate the PEFileKind value to the value expected by the Windows loader
6471 // PEFileKinds.Dll == 1
6472 // PEFileKinds.ConsoleApplication == 2
6473 // PEFileKinds.WindowApplication == 3
6476 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6477 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6479 if (assemblyb->pekind == 3)
6484 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6486 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6487 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6488 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6489 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6490 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6491 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6493 /* fill data directory entries */
6495 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6496 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6498 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6499 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6501 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6502 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6503 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6504 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6505 /* patch entrypoint name */
6506 if (assemblyb->pekind == 1)
6507 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6509 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6510 /* patch imported function RVA name */
6511 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6512 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6514 /* the import table */
6515 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6516 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6517 /* patch imported dll RVA name and other entries in the dir */
6518 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6519 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6520 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6521 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6522 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6523 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6525 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6526 value = (assembly->text_rva + assembly->imp_names_offset);
6527 *p++ = (value) & 0xff;
6528 *p++ = (value >> 8) & (0xff);
6529 *p++ = (value >> 16) & (0xff);
6530 *p++ = (value >> 24) & (0xff);
6532 /* the CLI header info */
6533 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6534 cli_header->ch_size = GUINT32_FROM_LE (72);
6535 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6536 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6537 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6538 if (assemblyb->entry_point) {
6539 guint32 table_idx = 0;
6540 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6541 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6542 table_idx = methodb->table_idx;
6544 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6546 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6548 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6550 /* The embedded managed resources */
6551 text_offset = assembly->text_rva + assembly->code.index;
6552 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6553 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6554 text_offset += assembly->resources.index;
6555 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6556 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6557 text_offset += assembly->meta_size;
6558 if (assembly->strong_name_size) {
6559 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6560 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6561 text_offset += assembly->strong_name_size;
6564 /* write the section tables and section content */
6565 section = (MonoSectionTable*)(pefile->data + section_start);
6566 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6567 static const char section_names [][7] = {
6568 ".text", ".rsrc", ".reloc"
6570 if (!assembly->sections [i].size)
6572 strcpy (section->st_name, section_names [i]);
6573 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6574 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6575 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6576 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6577 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6578 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6579 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6583 checked_write_file (file, pefile->data, pefile->index);
6585 mono_dynamic_stream_reset (pefile);
6587 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6588 if (!assembly->sections [i].size)
6591 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6592 g_error ("SetFilePointer returned %d\n", GetLastError ());
6595 case MONO_SECTION_TEXT:
6596 /* patch entry point */
6597 p = (guchar*)(assembly->code.data + 2);
6598 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6599 *p++ = (value) & 0xff;
6600 *p++ = (value >> 8) & 0xff;
6601 *p++ = (value >> 16) & 0xff;
6602 *p++ = (value >> 24) & 0xff;
6604 checked_write_file (file, assembly->code.data, assembly->code.index);
6605 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6606 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6607 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6610 g_free (assembly->image.raw_metadata);
6612 case MONO_SECTION_RELOC: {
6616 guint16 type_and_offset;
6620 g_assert (sizeof (reloc) == 12);
6622 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6623 reloc.block_size = GUINT32_FROM_LE (12);
6626 * the entrypoint is always at the start of the text section
6627 * 3 is IMAGE_REL_BASED_HIGHLOW
6628 * 2 is patch_size_rva - text_rva
6630 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6633 checked_write_file (file, &reloc, sizeof (reloc));
6637 case MONO_SECTION_RSRC:
6638 if (assembly->win32_res) {
6640 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6641 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6642 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6646 g_assert_not_reached ();
6650 /* check that the file is properly padded */
6651 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6652 g_error ("SetFilePointer returned %d\n", GetLastError ());
6653 if (! SetEndOfFile (file))
6654 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6656 mono_dynamic_stream_reset (&assembly->code);
6657 mono_dynamic_stream_reset (&assembly->us);
6658 mono_dynamic_stream_reset (&assembly->blob);
6659 mono_dynamic_stream_reset (&assembly->guid);
6660 mono_dynamic_stream_reset (&assembly->sheap);
6662 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6663 g_hash_table_destroy (assembly->blob_cache);
6664 assembly->blob_cache = NULL;
6669 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6672 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6674 g_assert_not_reached ();
6677 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6679 #ifndef DISABLE_REFLECTION_EMIT
6681 MonoReflectionModule *
6682 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6686 MonoImageOpenStatus status;
6687 MonoDynamicAssembly *assembly;
6688 guint32 module_count;
6689 MonoImage **new_modules;
6690 gboolean *new_modules_loaded;
6692 mono_error_init (error);
6694 name = mono_string_to_utf8 (fileName);
6696 image = mono_image_open (name, &status);
6698 if (status == MONO_IMAGE_ERROR_ERRNO)
6699 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6701 mono_error_set_bad_image_name (error, name, NULL);
6708 assembly = ab->dynamic_assembly;
6709 image->assembly = (MonoAssembly*)assembly;
6711 module_count = image->assembly->image->module_count;
6712 new_modules = g_new0 (MonoImage *, module_count + 1);
6713 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6715 if (image->assembly->image->modules)
6716 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6717 if (image->assembly->image->modules_loaded)
6718 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6719 new_modules [module_count] = image;
6720 new_modules_loaded [module_count] = TRUE;
6721 mono_image_addref (image);
6723 g_free (image->assembly->image->modules);
6724 image->assembly->image->modules = new_modules;
6725 image->assembly->image->modules_loaded = new_modules_loaded;
6726 image->assembly->image->module_count ++;
6728 mono_assembly_load_references (image, &status);
6730 mono_image_close (image);
6731 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6735 return mono_module_get_object_checked (mono_domain_get (), image, error);
6738 #endif /* DISABLE_REFLECTION_EMIT */
6741 * We need to return always the same object for MethodInfo, FieldInfo etc..
6742 * but we need to consider the reflected type.
6743 * type uses a different hash, since it uses custom hash/equal functions.
6748 MonoClass *refclass;
6752 reflected_equal (gconstpointer a, gconstpointer b) {
6753 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6754 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6756 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6760 reflected_hash (gconstpointer a) {
6761 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6762 return mono_aligned_addr_hash (ea->item);
6765 #define CHECK_OBJECT(t,p,k) \
6771 mono_domain_lock (domain); \
6772 if (!domain->refobject_hash) \
6773 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6774 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6775 mono_domain_unlock (domain); \
6778 mono_domain_unlock (domain); \
6781 #ifdef HAVE_BOEHM_GC
6782 /* ReflectedEntry doesn't need to be GC tracked */
6783 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6784 #define FREE_REFENTRY(entry) g_free ((entry))
6785 #define REFENTRY_REQUIRES_CLEANUP
6787 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6789 #define FREE_REFENTRY(entry)
6792 #define CACHE_OBJECT(t,p,o,k) \
6795 ReflectedEntry pe; \
6797 pe.refclass = (k); \
6798 mono_domain_lock (domain); \
6799 if (!domain->refobject_hash) \
6800 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6801 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6803 ReflectedEntry *e = ALLOC_REFENTRY; \
6805 e->refclass = (k); \
6806 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6809 mono_domain_unlock (domain); \
6814 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6816 mono_domain_lock (domain);
6817 if (domain->refobject_hash) {
6819 gpointer orig_pe, orig_value;
6822 pe.refclass = klass;
6823 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6824 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6825 FREE_REFENTRY (orig_pe);
6828 mono_domain_unlock (domain);
6831 #ifdef REFENTRY_REQUIRES_CLEANUP
6833 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6835 FREE_REFENTRY (key);
6840 mono_reflection_cleanup_domain (MonoDomain *domain)
6842 if (domain->refobject_hash) {
6843 /*let's avoid scanning the whole hashtable if not needed*/
6844 #ifdef REFENTRY_REQUIRES_CLEANUP
6845 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6847 mono_g_hash_table_destroy (domain->refobject_hash);
6848 domain->refobject_hash = NULL;
6852 #ifndef DISABLE_REFLECTION_EMIT
6854 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6856 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6860 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6862 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6866 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6868 MonoDynamicImage *image = moduleb->dynamic_image;
6869 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6870 mono_error_init (error);
6873 MonoImage **new_modules;
6875 char *name, *fqname;
6877 * FIXME: we already created an image in mono_image_basic_init (), but
6878 * we don't know which module it belongs to, since that is only
6879 * determined at assembly save time.
6881 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6882 name = mono_string_to_utf8 (ab->name);
6883 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6884 if (!is_ok (error)) {
6888 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6890 moduleb->module.image = &image->image;
6891 moduleb->dynamic_image = image;
6892 register_module (mono_object_domain (moduleb), moduleb, image);
6894 /* register the module with the assembly */
6895 ass = ab->dynamic_assembly->assembly.image;
6896 module_count = ass->module_count;
6897 new_modules = g_new0 (MonoImage *, module_count + 1);
6900 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6901 new_modules [module_count] = &image->image;
6902 mono_image_addref (&image->image);
6904 g_free (ass->modules);
6905 ass->modules = new_modules;
6906 ass->module_count ++;
6912 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6915 (void) image_module_basic_init (moduleb, &error);
6916 mono_error_set_pending_exception (&error);
6920 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6922 MonoDynamicImage *image = moduleb->dynamic_image;
6924 g_assert (type->type);
6925 image->wrappers_type = mono_class_from_mono_type (type->type);
6931 * mono_assembly_get_object:
6932 * @domain: an app domain
6933 * @assembly: an assembly
6935 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6937 MonoReflectionAssembly*
6938 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6941 MonoReflectionAssembly *result;
6942 result = mono_assembly_get_object_checked (domain, assembly, &error);
6943 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6947 * mono_assembly_get_object_checked:
6948 * @domain: an app domain
6949 * @assembly: an assembly
6951 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6953 MonoReflectionAssembly*
6954 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6956 MonoReflectionAssembly *res;
6958 mono_error_init (error);
6960 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6961 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6964 res->assembly = assembly;
6966 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6971 MonoReflectionModule*
6972 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6975 MonoReflectionModule *result;
6976 result = mono_module_get_object_checked (domain, image, &error);
6977 mono_error_cleanup (&error);
6981 MonoReflectionModule*
6982 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6984 MonoReflectionModule *res;
6987 mono_error_init (error);
6988 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6989 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6994 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6997 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6999 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7000 basename = g_path_get_basename (image->name);
7001 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7002 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7006 if (image->assembly->image == image) {
7007 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7011 if (image->assembly->image->modules) {
7012 for (i = 0; i < image->assembly->image->module_count; i++) {
7013 if (image->assembly->image->modules [i] == image)
7014 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7016 g_assert (res->token);
7020 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7023 MonoReflectionModule*
7024 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7027 MonoReflectionModule *result;
7028 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7029 mono_error_cleanup (&error);
7033 MonoReflectionModule*
7034 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7036 MonoReflectionModule *res;
7037 MonoTableInfo *table;
7038 guint32 cols [MONO_FILE_SIZE];
7040 guint32 i, name_idx;
7043 mono_error_init (error);
7045 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7049 table = &image->tables [MONO_TABLE_FILE];
7050 g_assert (table_index < table->rows);
7051 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7054 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7057 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7058 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7060 /* Check whenever the row has a corresponding row in the moduleref table */
7061 table = &image->tables [MONO_TABLE_MODULEREF];
7062 for (i = 0; i < table->rows; ++i) {
7063 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7064 val = mono_metadata_string_heap (image, name_idx);
7065 if (strcmp (val, name) == 0)
7066 res->image = image->modules [i];
7069 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7070 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7071 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7072 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7073 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7079 verify_safe_for_managed_space (MonoType *type)
7081 switch (type->type) {
7083 case MONO_TYPE_ARRAY:
7084 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7086 return verify_safe_for_managed_space (type->data.type);
7087 case MONO_TYPE_SZARRAY:
7088 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7089 case MONO_TYPE_GENERICINST: {
7090 MonoGenericInst *inst = type->data.generic_class->inst;
7094 for (i = 0; i < inst->type_argc; ++i)
7095 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7101 case MONO_TYPE_MVAR:
7109 mono_type_normalize (MonoType *type)
7112 MonoGenericClass *gclass;
7113 MonoGenericInst *ginst;
7115 MonoGenericContainer *gcontainer;
7116 MonoType **argv = NULL;
7117 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7119 if (type->type != MONO_TYPE_GENERICINST)
7122 gclass = type->data.generic_class;
7123 ginst = gclass->context.class_inst;
7124 if (!ginst->is_open)
7127 gtd = gclass->container_class;
7128 gcontainer = gtd->generic_container;
7129 argv = g_newa (MonoType*, ginst->type_argc);
7131 for (i = 0; i < ginst->type_argc; ++i) {
7132 MonoType *t = ginst->type_argv [i], *norm;
7133 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7134 is_denorm_gtd = FALSE;
7135 norm = mono_type_normalize (t);
7138 requires_rebind = TRUE;
7142 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7144 if (requires_rebind) {
7145 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7146 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7152 * mono_type_get_object:
7153 * @domain: an app domain
7156 * Return an System.MonoType object representing the type @type.
7159 mono_type_get_object (MonoDomain *domain, MonoType *type)
7162 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7163 mono_error_cleanup (&error);
7169 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7171 MonoType *norm_type;
7172 MonoReflectionType *res;
7175 mono_error_init (error);
7177 klass = mono_class_from_mono_type (type);
7179 /*we must avoid using @type as it might have come
7180 * from a mono_metadata_type_dup and the caller
7181 * expects that is can be freed.
7182 * Using the right type from
7184 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7186 /* void is very common */
7187 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7188 return (MonoReflectionType*)domain->typeof_void;
7191 * If the vtable of the given class was already created, we can use
7192 * the MonoType from there and avoid all locking and hash table lookups.
7194 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7195 * that the resulting object is different.
7197 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7198 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7199 if (vtable && vtable->type)
7200 return (MonoReflectionType *)vtable->type;
7203 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7204 mono_domain_lock (domain);
7205 if (!domain->type_hash)
7206 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7207 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7208 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7209 mono_domain_unlock (domain);
7210 mono_loader_unlock ();
7214 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7215 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7216 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7217 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7218 * artifact of how generics are encoded and should be transparent to managed code so we
7219 * need to weed out this diference when retrieving managed System.Type objects.
7221 norm_type = mono_type_normalize (type);
7222 if (norm_type != type) {
7223 res = mono_type_get_object_checked (domain, norm_type, error);
7224 if (!mono_error_ok (error))
7226 mono_g_hash_table_insert (domain->type_hash, type, res);
7227 mono_domain_unlock (domain);
7228 mono_loader_unlock ();
7232 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7233 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7236 if (!verify_safe_for_managed_space (type)) {
7237 mono_domain_unlock (domain);
7238 mono_loader_unlock ();
7239 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7243 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7244 gboolean is_type_done = TRUE;
7245 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7246 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7247 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7249 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7250 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7252 if (gparam->owner && gparam->owner->is_method) {
7253 MonoMethod *method = gparam->owner->owner.method;
7254 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7255 is_type_done = FALSE;
7256 } else if (gparam->owner && !gparam->owner->is_method) {
7257 MonoClass *klass = gparam->owner->owner.klass;
7258 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7259 is_type_done = FALSE;
7263 /* g_assert_not_reached (); */
7264 /* should this be considered an error condition? */
7265 if (is_type_done && !type->byref) {
7266 mono_domain_unlock (domain);
7267 mono_loader_unlock ();
7268 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7271 /* This is stored in vtables/JITted code so it has to be pinned */
7272 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7273 if (!mono_error_ok (error))
7277 mono_g_hash_table_insert (domain->type_hash, type, res);
7279 if (type->type == MONO_TYPE_VOID)
7280 domain->typeof_void = (MonoObject*)res;
7282 mono_domain_unlock (domain);
7283 mono_loader_unlock ();
7288 * mono_method_get_object:
7289 * @domain: an app domain
7291 * @refclass: the reflected type (can be NULL)
7293 * Return an System.Reflection.MonoMethod object representing the method @method.
7295 MonoReflectionMethod*
7296 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7299 MonoReflectionMethod *ret = NULL;
7300 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7301 mono_error_cleanup (&error);
7306 * mono_method_get_object_checked:
7307 * @domain: an app domain
7309 * @refclass: the reflected type (can be NULL)
7310 * @error: set on error.
7312 * Return an System.Reflection.MonoMethod object representing the method @method.
7313 * Returns NULL and sets @error on error.
7315 MonoReflectionMethod*
7316 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7319 * We use the same C representation for methods and constructors, but the type
7320 * name in C# is different.
7322 MonoReflectionType *rt;
7324 MonoReflectionMethod *ret;
7326 mono_error_init (error);
7328 if (method->is_inflated) {
7329 MonoReflectionGenericMethod *gret;
7332 refclass = method->klass;
7333 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7334 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7335 klass = mono_class_get_mono_generic_cmethod_class ();
7337 klass = mono_class_get_mono_generic_method_class ();
7339 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7340 if (!mono_error_ok (error))
7342 gret->method.method = method;
7344 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7346 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7347 if (!mono_error_ok (error))
7350 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7352 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7356 refclass = method->klass;
7358 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7359 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7360 klass = mono_class_get_mono_cmethod_class ();
7363 klass = mono_class_get_mono_method_class ();
7365 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7366 if (!mono_error_ok (error))
7368 ret->method = method;
7370 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7371 if (!mono_error_ok (error))
7374 MONO_OBJECT_SETREF (ret, reftype, rt);
7376 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7379 g_assert (!mono_error_ok (error));
7384 * mono_method_clear_object:
7386 * Clear the cached reflection objects for the dynamic method METHOD.
7389 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7392 g_assert (method_is_dynamic (method));
7394 klass = method->klass;
7396 clear_cached_object (domain, method, klass);
7397 klass = klass->parent;
7399 /* Added by mono_param_get_objects () */
7400 clear_cached_object (domain, &(method->signature), NULL);
7401 klass = method->klass;
7403 clear_cached_object (domain, &(method->signature), klass);
7404 klass = klass->parent;
7409 * mono_field_get_object:
7410 * @domain: an app domain
7414 * Return an System.Reflection.MonoField object representing the field @field
7417 MonoReflectionField*
7418 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7421 MonoReflectionField *result;
7422 result = mono_field_get_object_checked (domain, klass, field, &error);
7423 mono_error_cleanup (&error);
7428 * mono_field_get_object_checked:
7429 * @domain: an app domain
7432 * @error: set on error
7434 * Return an System.Reflection.MonoField object representing the field @field
7435 * in class @klass. On error, returns NULL and sets @error.
7437 MonoReflectionField*
7438 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7440 MonoReflectionType *rt;
7441 MonoReflectionField *res;
7443 mono_error_init (error);
7445 CHECK_OBJECT (MonoReflectionField *, field, klass);
7446 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7451 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7453 if (is_field_on_inst (field)) {
7454 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7456 rt = mono_type_get_object_checked (domain, field->type, error);
7457 if (!mono_error_ok (error))
7460 MONO_OBJECT_SETREF (res, type, rt);
7463 rt = mono_type_get_object_checked (domain, field->type, error);
7464 if (!mono_error_ok (error))
7467 MONO_OBJECT_SETREF (res, type, rt);
7469 res->attrs = mono_field_get_flags (field);
7471 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7475 * mono_property_get_object:
7476 * @domain: an app domain
7478 * @property: a property
7480 * Return an System.Reflection.MonoProperty object representing the property @property
7483 MonoReflectionProperty*
7484 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7487 MonoReflectionProperty *result;
7488 result = mono_property_get_object_checked (domain, klass, property, &error);
7489 mono_error_cleanup (&error);
7494 * mono_property_get_object:
7495 * @domain: an app domain
7497 * @property: a property
7498 * @error: set on error
7500 * Return an System.Reflection.MonoProperty object representing the property @property
7501 * in class @klass. On error returns NULL and sets @error.
7503 MonoReflectionProperty*
7504 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7506 MonoReflectionProperty *res;
7508 mono_error_init (error);
7510 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7511 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7515 res->property = property;
7516 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7520 * mono_event_get_object:
7521 * @domain: an app domain
7525 * Return an System.Reflection.MonoEvent object representing the event @event
7528 MonoReflectionEvent*
7529 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7532 MonoReflectionEvent *result;
7533 result = mono_event_get_object_checked (domain, klass, event, &error);
7534 mono_error_cleanup (&error);
7539 * mono_event_get_object_checked:
7540 * @domain: an app domain
7543 * @error: set on error
7545 * Return an System.Reflection.MonoEvent object representing the event @event
7546 * in class @klass. On failure sets @error and returns NULL
7548 MonoReflectionEvent*
7549 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7551 MonoReflectionEvent *res;
7552 MonoReflectionMonoEvent *mono_event;
7554 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7555 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7558 mono_event->klass = klass;
7559 mono_event->event = event;
7560 res = (MonoReflectionEvent*)mono_event;
7561 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7565 * mono_get_reflection_missing_object:
7566 * @domain: Domain where the object lives
7568 * Returns the System.Reflection.Missing.Value singleton object
7569 * (of type System.Reflection.Missing).
7571 * Used as the value for ParameterInfo.DefaultValue when Optional
7575 mono_get_reflection_missing_object (MonoDomain *domain)
7579 static MonoClassField *missing_value_field = NULL;
7581 if (!missing_value_field) {
7582 MonoClass *missing_klass;
7583 missing_klass = mono_class_get_missing_class ();
7584 mono_class_init (missing_klass);
7585 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7586 g_assert (missing_value_field);
7588 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7589 mono_error_assert_ok (&error);
7594 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7597 *dbnull = mono_get_dbnull_object (domain);
7602 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7604 if (!*reflection_missing)
7605 *reflection_missing = mono_get_reflection_missing_object (domain);
7606 return *reflection_missing;
7610 * mono_param_get_objects:
7611 * @domain: an app domain
7614 * Return an System.Reflection.ParameterInfo array object representing the parameters
7615 * in the method @method.
7618 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7620 static MonoClass *System_Reflection_ParameterInfo;
7621 static MonoClass *System_Reflection_ParameterInfo_array;
7622 MonoArray *res = NULL;
7623 MonoReflectionMethod *member = NULL;
7624 MonoReflectionParameter *param = NULL;
7625 char **names = NULL, **blobs = NULL;
7626 guint32 *types = NULL;
7627 MonoType *type = NULL;
7628 MonoObject *dbnull = NULL;
7629 MonoObject *missing = NULL;
7630 MonoMarshalSpec **mspecs = NULL;
7631 MonoMethodSignature *sig = NULL;
7632 MonoVTable *pinfo_vtable;
7633 MonoReflectionType *rt;
7636 mono_error_init (error);
7638 if (!System_Reflection_ParameterInfo_array) {
7641 klass = mono_class_get_mono_parameter_info_class ();
7643 mono_memory_barrier ();
7644 System_Reflection_ParameterInfo = klass;
7647 klass = mono_array_class_get (klass, 1);
7648 mono_memory_barrier ();
7649 System_Reflection_ParameterInfo_array = klass;
7652 sig = mono_method_signature_checked (method, error);
7653 if (!mono_error_ok (error))
7656 if (!sig->param_count) {
7657 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7664 /* Note: the cache is based on the address of the signature into the method
7665 * since we already cache MethodInfos with the method as keys.
7667 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7669 member = mono_method_get_object_checked (domain, method, refclass, error);
7672 names = g_new (char *, sig->param_count);
7673 mono_method_get_param_names (method, (const char **) names);
7675 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7676 mono_method_get_marshal_info (method, mspecs);
7678 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7682 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7683 for (i = 0; i < sig->param_count; ++i) {
7684 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7688 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7692 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7694 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7696 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7698 param->PositionImpl = i;
7699 param->AttrsImpl = sig->params [i]->attrs;
7701 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7702 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7703 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7705 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7709 blobs = g_new0 (char *, sig->param_count);
7710 types = g_new0 (guint32, sig->param_count);
7711 get_default_param_value_blobs (method, blobs, types);
7714 /* Build MonoType for the type from the Constant Table */
7716 type = g_new0 (MonoType, 1);
7717 type->type = (MonoTypeEnum)types [i];
7718 type->data.klass = NULL;
7719 if (types [i] == MONO_TYPE_CLASS)
7720 type->data.klass = mono_defaults.object_class;
7721 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7722 /* For enums, types [i] contains the base type */
7724 type->type = MONO_TYPE_VALUETYPE;
7725 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7727 type->data.klass = mono_class_from_mono_type (type);
7729 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7732 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7734 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7735 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7736 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7737 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7739 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7744 if (mspecs [i + 1]) {
7745 MonoReflectionMarshalAsAttribute* mobj;
7746 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7749 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7752 mono_array_setref (res, i, param);
7762 for (i = sig->param_count; i >= 0; i--) {
7764 mono_metadata_free_marshal_spec (mspecs [i]);
7772 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7776 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7779 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7780 mono_error_assert_ok (&error);
7785 * mono_method_body_get_object:
7786 * @domain: an app domain
7789 * Return an System.Reflection.MethodBody object representing the method @method.
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7795 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7796 mono_error_cleanup (&error);
7801 * mono_method_body_get_object_checked:
7802 * @domain: an app domain
7804 * @error: set on error
7806 * Return an System.Reflection.MethodBody object representing the
7807 * method @method. On failure, returns NULL and sets @error.
7809 MonoReflectionMethodBody*
7810 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7812 MonoReflectionMethodBody *ret;
7813 MonoMethodHeader *header;
7815 MonoReflectionType *rt;
7816 guint32 method_rva, local_var_sig_token;
7818 unsigned char format, flags;
7821 mono_error_init (error);
7823 /* for compatibility with .net */
7824 if (method_is_dynamic (method)) {
7825 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7829 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7831 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7832 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7833 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7834 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7835 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7838 image = method->klass->image;
7839 header = mono_method_get_header_checked (method, error);
7840 return_val_if_nok (error, NULL);
7842 if (!image_is_dynamic (image)) {
7843 /* Obtain local vars signature token */
7844 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7845 ptr = mono_image_rva_map (image, method_rva);
7846 flags = *(const unsigned char *) ptr;
7847 format = flags & METHOD_HEADER_FORMAT_MASK;
7849 case METHOD_HEADER_TINY_FORMAT:
7850 local_var_sig_token = 0;
7852 case METHOD_HEADER_FAT_FORMAT:
7856 local_var_sig_token = read32 (ptr);
7859 g_assert_not_reached ();
7862 local_var_sig_token = 0; //FIXME
7864 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7868 ret->init_locals = header->init_locals;
7869 ret->max_stack = header->max_stack;
7870 ret->local_var_sig_token = local_var_sig_token;
7871 MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7874 MONO_OBJECT_SETREF (ret, il, il_arr);
7875 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7878 MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7881 MONO_OBJECT_SETREF (ret, locals, locals_arr);
7882 for (i = 0; i < header->num_locals; ++i) {
7883 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7887 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7891 MONO_OBJECT_SETREF (info, local_type, rt);
7893 info->is_pinned = header->locals [i]->pinned;
7894 info->local_index = i;
7895 mono_array_setref (ret->locals, i, info);
7899 MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7902 MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7903 for (i = 0; i < header->num_clauses; ++i) {
7904 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7907 MonoExceptionClause *clause = &header->clauses [i];
7909 info->flags = clause->flags;
7910 info->try_offset = clause->try_offset;
7911 info->try_length = clause->try_len;
7912 info->handler_offset = clause->handler_offset;
7913 info->handler_length = clause->handler_len;
7914 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7915 info->filter_offset = clause->data.filter_offset;
7916 else if (clause->data.catch_class) {
7917 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7921 MONO_OBJECT_SETREF (info, catch_type, rt);
7924 mono_array_setref (ret->clauses, i, info);
7927 mono_metadata_free_mh (header);
7928 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7932 mono_metadata_free_mh (header);
7937 * mono_get_dbnull_object:
7938 * @domain: Domain where the object lives
7940 * Returns the System.DBNull.Value singleton object
7942 * Used as the value for ParameterInfo.DefaultValue
7945 mono_get_dbnull_object (MonoDomain *domain)
7949 static MonoClassField *dbnull_value_field = NULL;
7951 if (!dbnull_value_field) {
7952 MonoClass *dbnull_klass;
7953 dbnull_klass = mono_class_get_dbnull_class ();
7954 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7955 g_assert (dbnull_value_field);
7957 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7958 mono_error_assert_ok (&error);
7963 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7965 guint32 param_index, i, lastp, crow = 0;
7966 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7969 MonoClass *klass = method->klass;
7970 MonoImage *image = klass->image;
7971 MonoMethodSignature *methodsig = mono_method_signature (method);
7973 MonoTableInfo *constt;
7974 MonoTableInfo *methodt;
7975 MonoTableInfo *paramt;
7977 if (!methodsig->param_count)
7980 mono_class_init (klass);
7982 if (image_is_dynamic (klass->image)) {
7983 MonoReflectionMethodAux *aux;
7984 if (method->is_inflated)
7985 method = ((MonoMethodInflated*)method)->declaring;
7986 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7987 if (aux && aux->param_defaults) {
7988 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7989 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7994 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7995 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7996 constt = &image->tables [MONO_TABLE_CONSTANT];
7998 idx = mono_method_get_index (method) - 1;
7999 g_assert (idx != -1);
8001 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8002 if (idx + 1 < methodt->rows)
8003 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8005 lastp = paramt->rows + 1;
8007 for (i = param_index; i < lastp; ++i) {
8010 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8011 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8013 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8016 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8021 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8022 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8023 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8030 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8035 MonoType *basetype = type;
8037 mono_error_init (error);
8042 klass = mono_class_from_mono_type (type);
8043 if (klass->valuetype) {
8044 object = mono_object_new_checked (domain, klass, error);
8045 return_val_if_nok (error, NULL);
8046 retval = ((gchar *) object + sizeof (MonoObject));
8047 if (klass->enumtype)
8048 basetype = mono_class_enum_basetype (klass);
8053 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
8060 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8063 gboolean quoted = FALSE;
8065 memset (assembly, 0, sizeof (MonoAssemblyName));
8066 assembly->culture = "";
8067 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8074 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8085 /* Remove trailing whitespace */
8087 while (*s && g_ascii_isspace (*s))
8090 while (g_ascii_isspace (*p))
8093 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8095 assembly->major = strtoul (p, &s, 10);
8096 if (s == p || *s != '.')
8099 assembly->minor = strtoul (p, &s, 10);
8100 if (s == p || *s != '.')
8103 assembly->build = strtoul (p, &s, 10);
8104 if (s == p || *s != '.')
8107 assembly->revision = strtoul (p, &s, 10);
8111 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8113 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8114 assembly->culture = "";
8117 assembly->culture = p;
8118 while (*p && *p != ',') {
8122 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8124 if (strncmp (p, "null", 4) == 0) {
8129 while (*p && *p != ',') {
8132 len = (p - start + 1);
8133 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8134 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8135 g_strlcpy ((char*)assembly->public_key_token, start, len);
8138 while (*p && *p != ',')
8142 while (g_ascii_isspace (*p) || *p == ',') {
8156 * mono_reflection_parse_type:
8159 * Parse a type name as accepted by the GetType () method and output the info
8160 * extracted in the info structure.
8161 * the name param will be mangled, so, make a copy before passing it to this function.
8162 * The fields in info will be valid until the memory pointed to by name is valid.
8164 * See also mono_type_get_name () below.
8166 * Returns: 0 on parse error.
8169 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8170 MonoTypeNameParse *info)
8172 char *start, *p, *w, *last_point, *startn;
8173 int in_modifiers = 0;
8174 int isbyref = 0, rank = 0, isptr = 0;
8176 start = p = w = name;
8178 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8179 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8180 info->name = info->name_space = NULL;
8181 info->nested = NULL;
8182 info->modifiers = NULL;
8183 info->type_arguments = NULL;
8185 /* last_point separates the namespace from the name */
8188 while (*p == ' ') p++, start++, w++, name++;
8193 *p = 0; /* NULL terminate the name */
8195 info->nested = g_list_append (info->nested, startn);
8196 /* we have parsed the nesting namespace + name */
8200 info->name_space = start;
8202 info->name = last_point + 1;
8204 info->name_space = (char *)"";
8232 info->name_space = start;
8234 info->name = last_point + 1;
8236 info->name_space = (char *)"";
8243 if (isbyref) /* only one level allowed by the spec */
8247 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8251 if (isbyref) /* pointer to ref not okay */
8253 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8258 if (isbyref) /* array of ref and generic ref are not okay */
8260 //Decide if it's an array of a generic argument list
8265 if (*p == ',' || *p == '*' || *p == ']') { //array
8273 else if (*p == '*') /* '*' means unknown lower bound */
8274 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8281 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8283 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8286 info->type_arguments = g_ptr_array_new ();
8288 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8289 gboolean fqname = FALSE;
8291 g_ptr_array_add (info->type_arguments, subinfo);
8293 while (*p == ' ') p++;
8299 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8302 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8303 if (fqname && (*p != ']')) {
8311 while (*p && (*p != ']'))
8319 if (g_ascii_isspace (*aname)) {
8326 !assembly_name_to_aname (&subinfo->assembly, aname))
8328 } else if (fqname && (*p == ']')) {
8350 if (g_ascii_isspace (*p)) {
8357 return 0; /* missing assembly name */
8358 if (!assembly_name_to_aname (&info->assembly, p))
8364 if (info->assembly.name)
8367 // *w = 0; /* terminate class name */
8369 if (!info->name || !*info->name)
8373 /* add other consistency checks */
8379 * mono_identifier_unescape_type_name_chars:
8380 * @identifier: the display name of a mono type
8383 * The name in internal form, that is without escaping backslashes.
8385 * The string is modified in place!
8388 mono_identifier_unescape_type_name_chars(char* identifier)
8393 for (w = r = identifier; *r != 0; r++)
8411 mono_identifier_unescape_info (MonoTypeNameParse* info);
8414 unescape_each_type_argument(void* data, void* user_data)
8416 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8417 mono_identifier_unescape_info (info);
8421 unescape_each_nested_name (void* data, void* user_data)
8423 char* nested_name = (char*) data;
8424 mono_identifier_unescape_type_name_chars(nested_name);
8428 * mono_identifier_unescape_info:
8430 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8434 * Destructively updates the info by unescaping the identifiers that
8435 * comprise the type namespace, name, nested types (if any) and
8436 * generic type arguments (if any).
8438 * The resulting info has the names in internal form.
8442 mono_identifier_unescape_info (MonoTypeNameParse *info)
8446 mono_identifier_unescape_type_name_chars(info->name_space);
8447 mono_identifier_unescape_type_name_chars(info->name);
8448 // but don't escape info->assembly
8449 if (info->type_arguments)
8450 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8452 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8456 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8458 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8460 mono_identifier_unescape_info (info);
8466 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8468 gboolean type_resolve = FALSE;
8470 MonoImage *rootimage = image;
8472 mono_error_init (error);
8474 if (info->assembly.name) {
8475 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8476 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8478 * This could happen in the AOT compiler case when the search hook is not
8481 assembly = image->assembly;
8483 /* then we must load the assembly ourselve - see #60439 */
8484 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8488 image = assembly->image;
8489 } else if (!image) {
8490 image = mono_defaults.corlib;
8493 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8494 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8495 mono_error_cleanup (error);
8496 image = mono_defaults.corlib;
8497 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8504 * mono_reflection_get_type_internal:
8506 * Returns: may return NULL on success, sets error on failure.
8509 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8514 gboolean bounded = FALSE;
8516 mono_error_init (error);
8518 image = mono_defaults.corlib;
8521 rootimage = mono_defaults.corlib;
8524 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8526 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8531 for (mod = info->nested; mod; mod = mod->next) {
8532 gpointer iter = NULL;
8536 mono_class_init (parent);
8538 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8540 char *nested_name, *nested_nspace;
8541 gboolean match = TRUE;
8543 lastp = strrchr ((const char *)mod->data, '.');
8545 /* Nested classes can have namespaces */
8548 nested_name = g_strdup (lastp + 1);
8549 nspace_len = lastp - (char*)mod->data;
8550 nested_nspace = (char *)g_malloc (nspace_len + 1);
8551 memcpy (nested_nspace, mod->data, nspace_len);
8552 nested_nspace [nspace_len] = '\0';
8555 nested_name = (char *)mod->data;
8556 nested_nspace = NULL;
8559 if (nested_nspace) {
8561 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8564 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8570 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8573 if (strcmp (klass->name, nested_name) != 0)
8578 g_free (nested_name);
8579 g_free (nested_nspace);
8591 if (info->type_arguments) {
8592 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8593 MonoReflectionType *the_type;
8597 for (i = 0; i < info->type_arguments->len; i++) {
8598 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8600 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8601 if (!type_args [i]) {
8607 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8611 instance = mono_reflection_bind_generic_parameters (
8612 the_type, info->type_arguments->len, type_args, error);
8618 klass = mono_class_from_mono_type (instance);
8621 for (mod = info->modifiers; mod; mod = mod->next) {
8622 modval = GPOINTER_TO_UINT (mod->data);
8623 if (!modval) { /* byref: must be last modifier */
8624 return &klass->this_arg;
8625 } else if (modval == -1) {
8626 klass = mono_ptr_class_get (&klass->byval_arg);
8627 } else if (modval == -2) {
8629 } else { /* array rank */
8630 klass = mono_bounded_array_class_get (klass, modval, bounded);
8634 return &klass->byval_arg;
8638 * mono_reflection_get_type:
8639 * @image: a metadata context
8640 * @info: type description structure
8641 * @ignorecase: flag for case-insensitive string compares
8642 * @type_resolve: whenever type resolve was already tried
8644 * Build a MonoType from the type description in @info.
8649 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8651 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8652 mono_error_cleanup (&error);
8657 * mono_reflection_get_type_checked:
8658 * @rootimage: the image of the currently active managed caller
8659 * @image: a metadata context
8660 * @info: type description structure
8661 * @ignorecase: flag for case-insensitive string compares
8662 * @type_resolve: whenever type resolve was already tried
8663 * @error: set on error.
8665 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8669 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8670 mono_error_init (error);
8671 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8676 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8678 MonoReflectionAssemblyBuilder *abuilder;
8682 mono_error_init (error);
8683 g_assert (assembly_is_dynamic (assembly));
8684 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8688 /* Enumerate all modules */
8691 if (abuilder->modules) {
8692 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8693 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8694 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8697 if (!mono_error_ok (error))
8702 if (!type && abuilder->loaded_modules) {
8703 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8704 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8705 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8708 if (!mono_error_ok (error))
8717 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8720 MonoReflectionAssembly *assembly;
8724 mono_error_init (error);
8726 if (image && image_is_dynamic (image))
8727 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8729 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8731 return_val_if_nok (error, NULL);
8735 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8742 *type_resolve = TRUE;
8745 /* Reconstruct the type name */
8746 fullName = g_string_new ("");
8747 if (info->name_space && (info->name_space [0] != '\0'))
8748 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8750 g_string_printf (fullName, "%s", info->name);
8751 for (mod = info->nested; mod; mod = mod->next)
8752 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8754 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8755 if (!is_ok (error)) {
8756 g_string_free (fullName, TRUE);
8761 if (assembly_is_dynamic (assembly->assembly))
8762 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8763 info, ignorecase, error);
8765 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8766 info, ignorecase, error);
8768 g_string_free (fullName, TRUE);
8769 return_val_if_nok (error, NULL);
8774 mono_reflection_free_type_info (MonoTypeNameParse *info)
8776 g_list_free (info->modifiers);
8777 g_list_free (info->nested);
8779 if (info->type_arguments) {
8782 for (i = 0; i < info->type_arguments->len; i++) {
8783 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8785 mono_reflection_free_type_info (subinfo);
8786 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8790 g_ptr_array_free (info->type_arguments, TRUE);
8795 * mono_reflection_type_from_name:
8797 * @image: a metadata context (can be NULL).
8799 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8800 * it defaults to get the type from @image or, if @image is NULL or loading
8801 * from it fails, uses corlib.
8805 mono_reflection_type_from_name (char *name, MonoImage *image)
8808 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8809 mono_error_cleanup (&error);
8814 * mono_reflection_type_from_name_checked:
8816 * @image: a metadata context (can be NULL).
8817 * @error: set on errror.
8819 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8820 * it defaults to get the type from @image or, if @image is NULL or loading
8821 * from it fails, uses corlib. On failure returns NULL and sets @error.
8825 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8827 MonoType *type = NULL;
8828 MonoTypeNameParse info;
8831 mono_error_init (error);
8832 /* Make a copy since parse_type modifies its argument */
8833 tmp = g_strdup (name);
8835 /*g_print ("requested type %s\n", str);*/
8836 if (mono_reflection_parse_type (tmp, &info)) {
8837 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8838 if (!is_ok (error)) {
8840 mono_reflection_free_type_info (&info);
8846 mono_reflection_free_type_info (&info);
8851 * mono_reflection_get_token:
8853 * Return the metadata token of OBJ which should be an object
8854 * representing a metadata element.
8857 mono_reflection_get_token (MonoObject *obj)
8860 guint32 result = mono_reflection_get_token_checked (obj, &error);
8861 mono_error_assert_ok (&error);
8866 * mono_reflection_get_token_checked:
8868 * @error: set on error
8870 * Return the metadata token of @obj which should be an object
8871 * representing a metadata element. On failure sets @error.
8874 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8879 mono_error_init (error);
8881 klass = obj->vtable->klass;
8883 if (strcmp (klass->name, "MethodBuilder") == 0) {
8884 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8886 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8887 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8888 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8890 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8891 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8892 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8894 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8895 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8896 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8897 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8898 } else if (strcmp (klass->name, "MonoType") == 0) {
8899 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8900 return_val_if_nok (error, 0);
8901 MonoClass *mc = mono_class_from_mono_type (type);
8902 if (!mono_class_init (mc)) {
8903 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8907 token = mc->type_token;
8908 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8909 strcmp (klass->name, "MonoMethod") == 0 ||
8910 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8911 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8912 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8913 if (m->method->is_inflated) {
8914 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8915 return inflated->declaring->token;
8917 token = m->method->token;
8919 } else if (strcmp (klass->name, "MonoField") == 0) {
8920 MonoReflectionField *f = (MonoReflectionField*)obj;
8922 if (is_field_on_inst (f->field)) {
8923 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8925 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8926 int field_index = f->field - dgclass->fields;
8929 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8930 obj = dgclass->field_objects [field_index];
8931 return mono_reflection_get_token_checked (obj, error);
8934 token = mono_class_get_field_token (f->field);
8935 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8936 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8938 token = mono_class_get_property_token (p->property);
8939 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8940 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8942 token = mono_class_get_event_token (p->event);
8943 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8944 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8945 MonoClass *member_class = mono_object_class (p->MemberImpl);
8946 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8948 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8949 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8950 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8953 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8954 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8956 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8957 klass->name_space, klass->name);
8965 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8969 int slen = mono_metadata_decode_value (p, &p);
8971 mono_error_init (error);
8973 n = (char *)g_memdup (p, slen + 1);
8975 t = mono_reflection_type_from_name_checked (n, image, error);
8977 char *msg = g_strdup (mono_error_get_message (error));
8978 mono_error_cleanup (error);
8979 /* We don't free n, it's consumed by mono_error */
8980 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8987 return mono_class_from_mono_type (t);
8991 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8993 int slen, type = t->type;
8994 MonoClass *tklass = t->data.klass;
8996 mono_error_init (error);
9002 case MONO_TYPE_BOOLEAN: {
9003 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9008 case MONO_TYPE_CHAR:
9010 case MONO_TYPE_I2: {
9011 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9016 #if SIZEOF_VOID_P == 4
9022 case MONO_TYPE_I4: {
9023 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9028 #if SIZEOF_VOID_P == 8
9029 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9033 case MONO_TYPE_I8: {
9034 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9039 case MONO_TYPE_R8: {
9040 double *val = (double *)g_malloc (sizeof (double));
9045 case MONO_TYPE_VALUETYPE:
9046 if (t->data.klass->enumtype) {
9047 type = mono_class_enum_basetype (t->data.klass)->type;
9050 MonoClass *k = t->data.klass;
9052 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9053 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9059 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9062 case MONO_TYPE_STRING:
9063 if (*p == (char)0xFF) {
9067 slen = mono_metadata_decode_value (p, &p);
9069 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9070 case MONO_TYPE_CLASS: {
9071 MonoReflectionType *rt;
9074 if (*p == (char)0xFF) {
9079 slen = mono_metadata_decode_value (p, &p);
9080 n = (char *)g_memdup (p, slen + 1);
9082 t = mono_reflection_type_from_name_checked (n, image, error);
9084 char *msg = g_strdup (mono_error_get_message (error));
9085 mono_error_cleanup (error);
9086 /* We don't free n, it's consumed by mono_error */
9087 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9094 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9095 if (!mono_error_ok (error))
9100 case MONO_TYPE_OBJECT: {
9103 MonoClass *subc = NULL;
9108 } else if (subt == 0x0E) {
9109 type = MONO_TYPE_STRING;
9111 } else if (subt == 0x1D) {
9112 MonoType simple_type = {{0}};
9116 type = MONO_TYPE_SZARRAY;
9117 if (etype == 0x50) {
9118 tklass = mono_defaults.systemtype_class;
9119 } else if (etype == 0x55) {
9120 tklass = load_cattr_enum_type (image, p, &p, error);
9121 if (!mono_error_ok (error))
9125 /* See Partition II, Appendix B3 */
9126 etype = MONO_TYPE_OBJECT;
9127 simple_type.type = (MonoTypeEnum)etype;
9128 tklass = mono_class_from_mono_type (&simple_type);
9131 } else if (subt == 0x55) {
9134 slen = mono_metadata_decode_value (p, &p);
9135 n = (char *)g_memdup (p, slen + 1);
9137 t = mono_reflection_type_from_name_checked (n, image, error);
9139 char *msg = g_strdup (mono_error_get_message (error));
9140 mono_error_cleanup (error);
9141 /* We don't free n, it's consumed by mono_error */
9142 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9148 subc = mono_class_from_mono_type (t);
9149 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9150 MonoType simple_type = {{0}};
9151 simple_type.type = (MonoTypeEnum)subt;
9152 subc = mono_class_from_mono_type (&simple_type);
9154 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9156 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9158 if (mono_error_ok (error)) {
9159 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9160 g_assert (!subc->has_references);
9161 if (mono_error_ok (error))
9162 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9168 case MONO_TYPE_SZARRAY: {
9170 guint32 i, alen, basetype;
9173 if (alen == 0xffffffff) {
9177 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9178 return_val_if_nok (error, NULL);
9179 basetype = tklass->byval_arg.type;
9180 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9181 basetype = mono_class_enum_basetype (tklass)->type;
9186 case MONO_TYPE_BOOLEAN:
9187 for (i = 0; i < alen; i++) {
9188 MonoBoolean val = *p++;
9189 mono_array_set (arr, MonoBoolean, i, val);
9192 case MONO_TYPE_CHAR:
9195 for (i = 0; i < alen; i++) {
9196 guint16 val = read16 (p);
9197 mono_array_set (arr, guint16, i, val);
9204 for (i = 0; i < alen; i++) {
9205 guint32 val = read32 (p);
9206 mono_array_set (arr, guint32, i, val);
9211 for (i = 0; i < alen; i++) {
9214 mono_array_set (arr, double, i, val);
9220 for (i = 0; i < alen; i++) {
9221 guint64 val = read64 (p);
9222 mono_array_set (arr, guint64, i, val);
9226 case MONO_TYPE_CLASS:
9227 case MONO_TYPE_OBJECT:
9228 case MONO_TYPE_STRING:
9229 case MONO_TYPE_SZARRAY:
9230 for (i = 0; i < alen; i++) {
9231 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9232 if (!mono_error_ok (error))
9234 mono_array_setref (arr, i, item);
9238 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9244 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9250 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9252 mono_error_init (error);
9254 gboolean is_ref = type_is_reference (t);
9256 void *val = load_cattr_value (image, t, p, end, error);
9257 if (!is_ok (error)) {
9264 return (MonoObject*)val;
9266 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9272 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9274 static MonoMethod *ctor;
9276 void *params [2], *unboxed;
9278 mono_error_init (error);
9281 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9283 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9284 return_val_if_nok (error, NULL);
9287 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9288 return_val_if_nok (error, NULL);
9289 unboxed = mono_object_unbox (retval);
9291 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9292 return_val_if_nok (error, NULL);
9298 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9300 static MonoMethod *ctor;
9302 void *unboxed, *params [2];
9304 mono_error_init (error);
9307 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9310 params [1] = typedarg;
9311 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9312 return_val_if_nok (error, NULL);
9314 unboxed = mono_object_unbox (retval);
9316 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9317 return_val_if_nok (error, NULL);
9323 type_is_reference (MonoType *type)
9325 switch (type->type) {
9326 case MONO_TYPE_BOOLEAN:
9327 case MONO_TYPE_CHAR:
9340 case MONO_TYPE_VALUETYPE:
9348 free_param_data (MonoMethodSignature *sig, void **params) {
9350 for (i = 0; i < sig->param_count; ++i) {
9351 if (!type_is_reference (sig->params [i]))
9352 g_free (params [i]);
9357 * Find the field index in the metadata FieldDef table.
9360 find_field_index (MonoClass *klass, MonoClassField *field) {
9363 for (i = 0; i < klass->field.count; ++i) {
9364 if (field == &klass->fields [i])
9365 return klass->field.first + 1 + i;
9371 * Find the property index in the metadata Property table.
9374 find_property_index (MonoClass *klass, MonoProperty *property) {
9377 for (i = 0; i < klass->ext->property.count; ++i) {
9378 if (property == &klass->ext->properties [i])
9379 return klass->ext->property.first + 1 + i;
9385 * Find the event index in the metadata Event table.
9388 find_event_index (MonoClass *klass, MonoEvent *event) {
9391 for (i = 0; i < klass->ext->event.count; ++i) {
9392 if (event == &klass->ext->events [i])
9393 return klass->ext->event.first + 1 + i;
9399 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9401 const char *p = (const char*)data;
9403 guint32 i, j, num_named;
9405 void *params_buf [32];
9406 void **params = NULL;
9407 MonoMethodSignature *sig;
9409 mono_error_init (error);
9411 mono_class_init (method->klass);
9413 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9414 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9419 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9420 if (!mono_error_ok (error)) return NULL;
9422 mono_runtime_invoke_checked (method, attr, NULL, error);
9423 if (!mono_error_ok (error))
9429 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9432 /*g_print ("got attr %s\n", method->klass->name);*/
9434 sig = mono_method_signature (method);
9435 if (sig->param_count < 32) {
9436 params = params_buf;
9437 memset (params, 0, sizeof (void*) * sig->param_count);
9439 /* Allocate using GC so it gets GC tracking */
9440 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9445 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9446 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9447 if (!mono_error_ok (error))
9452 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9453 if (!mono_error_ok (error)) goto fail;
9455 MonoObject *exc = NULL;
9456 mono_runtime_try_invoke (method, attr, params, &exc, error);
9457 if (!mono_error_ok (error))
9460 mono_error_set_exception_instance (error, (MonoException*)exc);
9464 num_named = read16 (named);
9466 for (j = 0; j < num_named; j++) {
9468 char *name, named_type, data_type;
9469 named_type = *named++;
9470 data_type = *named++; /* type of data */
9471 if (data_type == MONO_TYPE_SZARRAY)
9472 data_type = *named++;
9473 if (data_type == MONO_TYPE_ENUM) {
9476 type_len = mono_metadata_decode_blob_size (named, &named);
9477 type_name = (char *)g_malloc (type_len + 1);
9478 memcpy (type_name, named, type_len);
9479 type_name [type_len] = 0;
9481 /* FIXME: lookup the type and check type consistency */
9484 name_len = mono_metadata_decode_blob_size (named, &named);
9485 name = (char *)g_malloc (name_len + 1);
9486 memcpy (name, named, name_len);
9487 name [name_len] = 0;
9489 if (named_type == 0x53) {
9490 MonoClassField *field;
9493 /* how this fail is a blackbox */
9494 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9496 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9501 val = load_cattr_value (image, field->type, named, &named, error);
9502 if (!mono_error_ok (error)) {
9504 if (!type_is_reference (field->type))
9509 mono_field_set_value (attr, field, val);
9510 if (!type_is_reference (field->type))
9512 } else if (named_type == 0x54) {
9515 MonoType *prop_type;
9517 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9520 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9526 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9531 /* can we have more that 1 arg in a custom attr named property? */
9532 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9533 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9535 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9536 if (!mono_error_ok (error)) {
9538 if (!type_is_reference (prop_type))
9539 g_free (pparams [0]);
9544 mono_property_set_value_checked (prop, attr, pparams, error);
9545 if (!type_is_reference (prop_type))
9546 g_free (pparams [0]);
9547 if (!is_ok (error)) {
9555 free_param_data (method->signature, params);
9556 if (params != params_buf)
9557 mono_gc_free_fixed (params);
9562 free_param_data (method->signature, params);
9563 if (params != params_buf)
9564 mono_gc_free_fixed (params);
9569 * mono_reflection_create_custom_attr_data_args:
9571 * Create an array of typed and named arguments from the cattr blob given by DATA.
9572 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9573 * NAMED_ARG_INFO will contain information about the named arguments.
9576 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)
9578 MonoArray *typedargs, *namedargs;
9579 MonoClass *attrklass;
9581 const char *p = (const char*)data;
9583 guint32 i, j, num_named;
9584 CattrNamedArg *arginfo = NULL;
9588 *named_arg_info = NULL;
9590 mono_error_init (error);
9592 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9593 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9597 mono_class_init (method->klass);
9599 domain = mono_domain_get ();
9601 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9604 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9605 return_if_nok (error);
9609 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9612 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9613 return_if_nok (error);
9614 mono_array_setref (typedargs, i, obj);
9618 num_named = read16 (named);
9619 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9620 return_if_nok (error);
9622 attrklass = method->klass;
9624 arginfo = g_new0 (CattrNamedArg, num_named);
9625 *named_arg_info = arginfo;
9627 for (j = 0; j < num_named; j++) {
9629 char *name, named_type, data_type;
9630 named_type = *named++;
9631 data_type = *named++; /* type of data */
9632 if (data_type == MONO_TYPE_SZARRAY)
9633 data_type = *named++;
9634 if (data_type == MONO_TYPE_ENUM) {
9637 type_len = mono_metadata_decode_blob_size (named, &named);
9638 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9641 type_name = (char *)g_malloc (type_len + 1);
9642 memcpy (type_name, named, type_len);
9643 type_name [type_len] = 0;
9645 /* FIXME: lookup the type and check type consistency */
9648 name_len = mono_metadata_decode_blob_size (named, &named);
9649 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9651 name = (char *)g_malloc (name_len + 1);
9652 memcpy (name, named, name_len);
9653 name [name_len] = 0;
9655 if (named_type == 0x53) {
9657 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9664 arginfo [j].type = field->type;
9665 arginfo [j].field = field;
9667 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9668 if (!is_ok (error)) {
9672 mono_array_setref (namedargs, j, obj);
9674 } else if (named_type == 0x54) {
9676 MonoType *prop_type;
9677 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9679 if (!prop || !prop->set) {
9684 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9685 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9687 arginfo [j].type = prop_type;
9688 arginfo [j].prop = prop;
9690 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9691 if (!is_ok (error)) {
9695 mono_array_setref (namedargs, j, obj);
9700 *typed_args = typedargs;
9701 *named_args = namedargs;
9704 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9706 *named_arg_info = NULL;
9710 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9713 MonoArray *typedargs, *namedargs;
9716 CattrNamedArg *arginfo = NULL;
9719 mono_error_init (error);
9727 image = assembly->assembly->image;
9728 method = ref_method->method;
9729 domain = mono_object_domain (ref_method);
9731 if (!mono_class_init (method->klass)) {
9732 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->klass));
9736 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9740 if (!typedargs || !namedargs)
9743 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9744 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9745 MonoObject *typedarg;
9747 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9750 mono_array_setref (typedargs, i, typedarg);
9753 for (i = 0; i < mono_array_length (namedargs); ++i) {
9754 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9755 MonoObject *typedarg, *namedarg, *minfo;
9757 if (arginfo [i].prop) {
9758 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9762 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9767 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9770 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9774 mono_array_setref (namedargs, i, namedarg);
9777 *ctor_args = typedargs;
9778 *named_args = namedargs;
9782 return mono_error_ok (error);
9786 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9789 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9790 mono_error_set_pending_exception (&error);
9794 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9796 static MonoMethod *ctor;
9802 mono_error_init (error);
9804 g_assert (image->assembly);
9807 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9809 domain = mono_domain_get ();
9810 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9811 return_val_if_nok (error, NULL);
9812 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9813 return_val_if_nok (error, NULL);
9814 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9815 return_val_if_nok (error, NULL);
9816 params [2] = (gpointer)&cattr->data;
9817 params [3] = &cattr->data_size;
9819 mono_runtime_invoke_checked (ctor, attr, params, error);
9820 return_val_if_nok (error, NULL);
9825 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9831 mono_error_init (error);
9834 for (i = 0; i < cinfo->num_attrs; ++i) {
9835 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9839 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9840 return_val_if_nok (error, NULL);
9842 for (i = 0; i < cinfo->num_attrs; ++i) {
9843 if (!cinfo->attrs [i].ctor) {
9844 /* The cattr type is not finished yet */
9845 /* We should include the type name but cinfo doesn't contain it */
9846 mono_error_set_type_load_name (error, NULL, NULL, "");
9849 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9850 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9851 if (!mono_error_ok (error))
9853 mono_array_setref (result, n, attr);
9861 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9864 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9865 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9871 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9877 mono_error_init (error);
9878 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9879 return_val_if_nok (error, NULL);
9880 for (i = 0; i < cinfo->num_attrs; ++i) {
9881 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9882 return_val_if_nok (error, NULL);
9883 mono_array_setref (result, i, attr);
9889 * mono_custom_attrs_from_index:
9891 * Returns: NULL if no attributes are found or if a loading error occurs.
9894 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9897 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9898 mono_error_cleanup (&error);
9902 * mono_custom_attrs_from_index_checked:
9904 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9907 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9909 guint32 mtoken, i, len;
9910 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9912 MonoCustomAttrInfo *ainfo;
9913 GList *tmp, *list = NULL;
9915 MonoCustomAttrEntry* attr;
9917 mono_error_init (error);
9919 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9921 i = mono_metadata_custom_attrs_from_index (image, idx);
9925 while (i < ca->rows) {
9926 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9928 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9931 len = g_list_length (list);
9934 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9935 ainfo->num_attrs = len;
9936 ainfo->image = image;
9937 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9938 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9939 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9940 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9941 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9942 mtoken |= MONO_TOKEN_METHOD_DEF;
9944 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9945 mtoken |= MONO_TOKEN_MEMBER_REF;
9948 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9951 attr = &ainfo->attrs [i - 1];
9952 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9954 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9960 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9961 /*FIXME raising an exception here doesn't make any sense*/
9962 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9967 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9968 attr->data_size = mono_metadata_decode_value (data, &data);
9969 attr->data = (guchar*)data;
9977 mono_custom_attrs_from_method (MonoMethod *method)
9980 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9981 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9986 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9990 mono_error_init (error);
9993 * An instantiated method has the same cattrs as the generic method definition.
9995 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9996 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9998 if (method->is_inflated)
9999 method = ((MonoMethodInflated *) method)->declaring;
10001 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10002 return lookup_custom_attr (method->klass->image, method);
10004 if (!method->token)
10005 /* Synthetic methods */
10008 idx = mono_method_get_index (method);
10009 idx <<= MONO_CUSTOM_ATTR_BITS;
10010 idx |= MONO_CUSTOM_ATTR_METHODDEF;
10011 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10014 MonoCustomAttrInfo*
10015 mono_custom_attrs_from_class (MonoClass *klass)
10018 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10019 mono_error_cleanup (&error);
10023 MonoCustomAttrInfo*
10024 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10028 mono_error_init (error);
10030 if (klass->generic_class)
10031 klass = klass->generic_class->container_class;
10033 if (image_is_dynamic (klass->image))
10034 return lookup_custom_attr (klass->image, klass);
10036 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10037 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10038 idx <<= MONO_CUSTOM_ATTR_BITS;
10039 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10041 idx = mono_metadata_token_index (klass->type_token);
10042 idx <<= MONO_CUSTOM_ATTR_BITS;
10043 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10045 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10048 MonoCustomAttrInfo*
10049 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10052 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10053 mono_error_cleanup (&error);
10057 MonoCustomAttrInfo*
10058 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10062 mono_error_init (error);
10064 if (image_is_dynamic (assembly->image))
10065 return lookup_custom_attr (assembly->image, assembly);
10066 idx = 1; /* there is only one assembly */
10067 idx <<= MONO_CUSTOM_ATTR_BITS;
10068 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10069 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10072 static MonoCustomAttrInfo*
10073 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10077 if (image_is_dynamic (image))
10078 return lookup_custom_attr (image, image);
10079 idx = 1; /* there is only one module */
10080 idx <<= MONO_CUSTOM_ATTR_BITS;
10081 idx |= MONO_CUSTOM_ATTR_MODULE;
10082 return mono_custom_attrs_from_index_checked (image, idx, error);
10085 MonoCustomAttrInfo*
10086 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10089 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10090 mono_error_cleanup (&error);
10094 MonoCustomAttrInfo*
10095 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10099 if (image_is_dynamic (klass->image)) {
10100 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10101 return lookup_custom_attr (klass->image, property);
10103 idx = find_property_index (klass, property);
10104 idx <<= MONO_CUSTOM_ATTR_BITS;
10105 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10106 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10109 MonoCustomAttrInfo*
10110 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10113 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10114 mono_error_cleanup (&error);
10118 MonoCustomAttrInfo*
10119 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10123 if (image_is_dynamic (klass->image)) {
10124 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10125 return lookup_custom_attr (klass->image, event);
10127 idx = find_event_index (klass, event);
10128 idx <<= MONO_CUSTOM_ATTR_BITS;
10129 idx |= MONO_CUSTOM_ATTR_EVENT;
10130 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10133 MonoCustomAttrInfo*
10134 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10137 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10138 mono_error_cleanup (&error);
10142 MonoCustomAttrInfo*
10143 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10146 mono_error_init (error);
10148 if (image_is_dynamic (klass->image)) {
10149 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10150 return lookup_custom_attr (klass->image, field);
10152 idx = find_field_index (klass, field);
10153 idx <<= MONO_CUSTOM_ATTR_BITS;
10154 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10155 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10159 * mono_custom_attrs_from_param:
10160 * @method: handle to the method that we want to retrieve custom parameter information from
10161 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10163 * The result must be released with mono_custom_attrs_free().
10165 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10167 MonoCustomAttrInfo*
10168 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10171 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10172 mono_error_cleanup (&error);
10177 * mono_custom_attrs_from_param_checked:
10178 * @method: handle to the method that we want to retrieve custom parameter information from
10179 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10180 * @error: set on error
10182 * The result must be released with mono_custom_attrs_free().
10184 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10186 MonoCustomAttrInfo*
10187 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10190 guint32 i, idx, method_index;
10191 guint32 param_list, param_last, param_pos, found;
10193 MonoReflectionMethodAux *aux;
10195 mono_error_init (error);
10198 * An instantiated method has the same cattrs as the generic method definition.
10200 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10201 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10203 if (method->is_inflated)
10204 method = ((MonoMethodInflated *) method)->declaring;
10206 if (image_is_dynamic (method->klass->image)) {
10207 MonoCustomAttrInfo *res, *ainfo;
10210 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10211 if (!aux || !aux->param_cattr)
10214 /* Need to copy since it will be freed later */
10215 ainfo = aux->param_cattr [param];
10218 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10219 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10220 memcpy (res, ainfo, size);
10224 image = method->klass->image;
10225 method_index = mono_method_get_index (method);
10228 ca = &image->tables [MONO_TABLE_METHOD];
10230 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10231 if (method_index == ca->rows) {
10232 ca = &image->tables [MONO_TABLE_PARAM];
10233 param_last = ca->rows + 1;
10235 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10236 ca = &image->tables [MONO_TABLE_PARAM];
10239 for (i = param_list; i < param_last; ++i) {
10240 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10241 if (param_pos == param) {
10249 idx <<= MONO_CUSTOM_ATTR_BITS;
10250 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10251 return mono_custom_attrs_from_index_checked (image, idx, error);
10255 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10259 for (i = 0; i < ainfo->num_attrs; ++i) {
10260 klass = ainfo->attrs [i].ctor->klass;
10261 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10268 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10271 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10272 mono_error_assert_ok (&error); /*FIXME proper error handling*/
10277 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10283 mono_error_init (error);
10286 for (i = 0; i < ainfo->num_attrs; ++i) {
10287 klass = ainfo->attrs [i].ctor->klass;
10288 if (mono_class_has_parent (klass, attr_klass)) {
10293 if (attr_index == -1)
10296 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10297 if (!mono_error_ok (error))
10299 return mono_array_get (attrs, MonoObject*, attr_index);
10303 * mono_reflection_get_custom_attrs_info:
10304 * @obj: a reflection object handle
10306 * Return the custom attribute info for attributes defined for the
10307 * reflection handle @obj. The objects.
10309 * FIXME this function leaks like a sieve for SRE objects.
10311 MonoCustomAttrInfo*
10312 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10315 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10316 mono_error_assert_ok (&error);
10321 * mono_reflection_get_custom_attrs_info_checked:
10322 * @obj: a reflection object handle
10323 * @error: set on error
10325 * Return the custom attribute info for attributes defined for the
10326 * reflection handle @obj. The objects.
10328 * On failure returns NULL and sets @error.
10330 * FIXME this function leaks like a sieve for SRE objects.
10332 MonoCustomAttrInfo*
10333 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10336 MonoCustomAttrInfo *cinfo = NULL;
10338 mono_error_init (error);
10340 klass = obj->vtable->klass;
10341 if (klass == mono_defaults.monotype_class) {
10342 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10343 return_val_if_nok (error, NULL);
10344 klass = mono_class_from_mono_type (type);
10345 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10346 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10347 return_val_if_nok (error, NULL);
10348 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10349 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10350 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10351 return_val_if_nok (error, NULL);
10352 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10353 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10354 cinfo = mono_custom_attrs_from_module (module->image, error);
10355 return_val_if_nok (error, NULL);
10356 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10357 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10358 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10359 return_val_if_nok (error, NULL);
10360 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10361 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10362 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10363 return_val_if_nok (error, NULL);
10364 } else if (strcmp ("MonoField", klass->name) == 0) {
10365 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10366 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10367 return_val_if_nok (error, NULL);
10368 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10369 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10370 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10371 return_val_if_nok (error, NULL);
10372 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10373 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10374 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10375 return_val_if_nok (error, NULL);
10376 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10377 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10378 MonoClass *member_class = mono_object_class (param->MemberImpl);
10379 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10380 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10381 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10382 return_val_if_nok (error, NULL);
10383 } else if (is_sr_mono_property (member_class)) {
10384 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10385 MonoMethod *method;
10386 if (!(method = prop->property->get))
10387 method = prop->property->set;
10390 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10391 return_val_if_nok (error, NULL);
10393 #ifndef DISABLE_REFLECTION_EMIT
10394 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10395 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10396 return_val_if_nok (error, NULL);
10397 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10398 return_val_if_nok (error, NULL);
10399 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10400 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10401 MonoMethod *method = NULL;
10402 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10403 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10404 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10405 method = ((MonoReflectionMethod *)c->cb)->method;
10407 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));
10409 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10410 return_val_if_nok (error, NULL);
10414 char *type_name = mono_type_get_full_name (member_class);
10415 mono_error_set_not_supported (error,
10416 "Custom attributes on a ParamInfo with member %s are not supported",
10418 g_free (type_name);
10421 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10422 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10423 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10424 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10425 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10426 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10427 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10428 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10429 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10430 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10431 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10432 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10433 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10434 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10435 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10436 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10437 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10438 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10439 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10440 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10441 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10442 return_val_if_nok (error, NULL);
10443 } else { /* handle other types here... */
10444 g_error ("get custom attrs not yet supported for %s", klass->name);
10451 * mono_reflection_get_custom_attrs_by_type:
10452 * @obj: a reflection object handle
10454 * Return an array with all the custom attributes defined of the
10455 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10456 * of that type are returned. The objects are fully build. Return NULL if a loading error
10460 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10463 MonoCustomAttrInfo *cinfo;
10465 mono_error_init (error);
10467 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10468 return_val_if_nok (error, NULL);
10470 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10471 if (!cinfo->cached)
10472 mono_custom_attrs_free (cinfo);
10476 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10483 * mono_reflection_get_custom_attrs:
10484 * @obj: a reflection object handle
10486 * Return an array with all the custom attributes defined of the
10487 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10491 mono_reflection_get_custom_attrs (MonoObject *obj)
10495 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10499 * mono_reflection_get_custom_attrs_data:
10500 * @obj: a reflection obj handle
10502 * Returns an array of System.Reflection.CustomAttributeData,
10503 * which include information about attributes reflected on
10504 * types loaded using the Reflection Only methods
10507 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10511 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10512 mono_error_cleanup (&error);
10517 * mono_reflection_get_custom_attrs_data_checked:
10518 * @obj: a reflection obj handle
10519 * @error: set on error
10521 * Returns an array of System.Reflection.CustomAttributeData,
10522 * which include information about attributes reflected on
10523 * types loaded using the Reflection Only methods
10526 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10529 MonoCustomAttrInfo *cinfo;
10531 mono_error_init (error);
10533 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10534 return_val_if_nok (error, NULL);
10536 result = mono_custom_attrs_data_construct (cinfo, error);
10537 if (!cinfo->cached)
10538 mono_custom_attrs_free (cinfo);
10539 return_val_if_nok (error, NULL);
10541 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10546 static MonoReflectionType*
10547 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10549 static MonoMethod *method_get_underlying_system_type = NULL;
10550 MonoReflectionType *rt;
10551 MonoMethod *usertype_method;
10553 mono_error_init (error);
10555 if (!method_get_underlying_system_type)
10556 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10558 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10560 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10567 is_corlib_type (MonoClass *klass)
10569 return klass->image == mono_defaults.corlib;
10572 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10573 static MonoClass *cached_class; \
10574 if (cached_class) \
10575 return cached_class == _class; \
10576 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10577 cached_class = _class; \
10584 #ifndef DISABLE_REFLECTION_EMIT
10586 is_sre_array (MonoClass *klass)
10588 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10592 is_sre_byref (MonoClass *klass)
10594 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10598 is_sre_pointer (MonoClass *klass)
10600 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10604 is_sre_generic_instance (MonoClass *klass)
10606 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10610 is_sre_type_builder (MonoClass *klass)
10612 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10616 is_sre_method_builder (MonoClass *klass)
10618 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10622 is_sre_ctor_builder (MonoClass *klass)
10624 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10628 is_sre_field_builder (MonoClass *klass)
10630 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10634 is_sre_method_on_tb_inst (MonoClass *klass)
10636 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10640 is_sre_ctor_on_tb_inst (MonoClass *klass)
10642 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10646 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10649 mono_error_init (error);
10656 if (is_usertype (ref)) {
10657 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10658 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10664 klass = mono_object_class (ref);
10666 if (is_sre_array (klass)) {
10668 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10669 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10670 return_val_if_nok (error, NULL);
10672 if (sre_array->rank == 0) //single dimentional array
10673 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10675 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10676 sre_array->type.type = res;
10678 } else if (is_sre_byref (klass)) {
10680 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10681 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10682 return_val_if_nok (error, NULL);
10684 res = &mono_class_from_mono_type (base)->this_arg;
10685 sre_byref->type.type = res;
10687 } else if (is_sre_pointer (klass)) {
10689 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10690 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10691 return_val_if_nok (error, NULL);
10693 res = &mono_ptr_class_get (base)->byval_arg;
10694 sre_pointer->type.type = res;
10696 } else if (is_sre_generic_instance (klass)) {
10697 MonoType *res, **types;
10698 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10701 count = mono_array_length (gclass->type_arguments);
10702 types = g_new0 (MonoType*, count);
10703 for (i = 0; i < count; ++i) {
10704 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10705 types [i] = mono_reflection_type_get_handle (t, error);
10706 if (!types[i] || !is_ok (error)) {
10712 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10715 gclass->type.type = res;
10719 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10724 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10727 mono_reflection_type_get_handle (type, &error);
10728 mono_error_set_pending_exception (&error);
10732 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10734 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10737 mono_error_init (error);
10739 MonoType *res = mono_reflection_type_get_handle (type, error);
10741 if (!res && is_ok (error)) {
10742 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10744 return_val_if_nok (error, FALSE);
10746 klass = mono_class_from_mono_type (res);
10748 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10749 mono_domain_lock (domain);
10751 if (!image_is_dynamic (klass->image)) {
10752 mono_class_setup_supertypes (klass);
10754 if (!domain->type_hash)
10755 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10756 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10757 mono_g_hash_table_insert (domain->type_hash, res, type);
10759 mono_domain_unlock (domain);
10760 mono_loader_unlock ();
10766 mono_reflection_register_with_runtime (MonoReflectionType *type)
10769 (void) reflection_register_with_runtime (type, &error);
10770 mono_error_set_pending_exception (&error);
10774 * LOCKING: Assumes the loader lock is held.
10776 static MonoMethodSignature*
10777 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10778 MonoMethodSignature *sig;
10781 mono_error_init (error);
10783 count = parameters? mono_array_length (parameters): 0;
10785 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10786 sig->param_count = count;
10787 sig->sentinelpos = -1; /* FIXME */
10788 for (i = 0; i < count; ++i) {
10789 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10790 if (!is_ok (error)) {
10791 image_g_free (image, sig);
10799 * LOCKING: Assumes the loader lock is held.
10801 static MonoMethodSignature*
10802 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10803 MonoMethodSignature *sig;
10805 mono_error_init (error);
10807 sig = parameters_to_signature (image, ctor->parameters, error);
10808 return_val_if_nok (error, NULL);
10809 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10810 sig->ret = &mono_defaults.void_class->byval_arg;
10815 * LOCKING: Assumes the loader lock is held.
10817 static MonoMethodSignature*
10818 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10819 MonoMethodSignature *sig;
10821 mono_error_init (error);
10823 sig = parameters_to_signature (image, method->parameters, error);
10824 return_val_if_nok (error, NULL);
10825 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10826 if (method->rtype) {
10827 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10828 if (!is_ok (error)) {
10829 image_g_free (image, sig);
10833 sig->ret = &mono_defaults.void_class->byval_arg;
10835 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10839 static MonoMethodSignature*
10840 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10841 MonoMethodSignature *sig;
10843 mono_error_init (error);
10845 sig = parameters_to_signature (NULL, method->parameters, error);
10846 return_val_if_nok (error, NULL);
10847 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10848 if (method->rtype) {
10849 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10850 if (!is_ok (error)) {
10855 sig->ret = &mono_defaults.void_class->byval_arg;
10857 sig->generic_param_count = 0;
10862 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10864 mono_error_init (error);
10865 MonoClass *klass = mono_object_class (prop);
10866 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10867 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10868 *name = mono_string_to_utf8 (pb->name);
10869 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10871 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10872 *name = g_strdup (p->property->name);
10873 if (p->property->get)
10874 *type = mono_method_signature (p->property->get)->ret;
10876 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10881 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10883 mono_error_init (error);
10884 MonoClass *klass = mono_object_class (field);
10885 if (strcmp (klass->name, "FieldBuilder") == 0) {
10886 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10887 *name = mono_string_to_utf8 (fb->name);
10888 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10890 MonoReflectionField *f = (MonoReflectionField *)field;
10891 *name = g_strdup (mono_field_get_name (f->field));
10892 *type = f->field->type;
10896 #else /* DISABLE_REFLECTION_EMIT */
10899 mono_reflection_register_with_runtime (MonoReflectionType *type)
10901 /* This is empty */
10905 is_sre_type_builder (MonoClass *klass)
10911 is_sre_generic_instance (MonoClass *klass)
10917 init_type_builder_generics (MonoObject *type, MonoError *error)
10919 mono_error_init (error);
10922 #endif /* !DISABLE_REFLECTION_EMIT */
10926 is_sr_mono_field (MonoClass *klass)
10928 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10932 is_sr_mono_property (MonoClass *klass)
10934 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10938 is_sr_mono_method (MonoClass *klass)
10940 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10944 is_sr_mono_cmethod (MonoClass *klass)
10946 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10950 is_sr_mono_generic_method (MonoClass *klass)
10952 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10956 is_sr_mono_generic_cmethod (MonoClass *klass)
10958 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10962 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10964 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10968 is_usertype (MonoReflectionType *ref)
10970 MonoClass *klass = mono_object_class (ref);
10971 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10974 static MonoReflectionType*
10975 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10977 mono_error_init (error);
10978 if (!type || type->type)
10981 if (is_usertype (type)) {
10982 type = mono_reflection_type_get_underlying_system_type (type, error);
10983 return_val_if_nok (error, NULL);
10984 if (is_usertype (type)) {
10985 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10993 * encode_cattr_value:
10994 * Encode a value in a custom attribute stream of bytes.
10995 * The value to encode is either supplied as an object in argument val
10996 * (valuetypes are boxed), or as a pointer to the data in the
10998 * @type represents the type of the value
10999 * @buffer is the start of the buffer
11000 * @p the current position in the buffer
11001 * @buflen contains the size of the buffer and is used to return the new buffer size
11002 * if this needs to be realloced.
11003 * @retbuffer and @retp return the start and the position of the buffer
11004 * @error set on error.
11007 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11009 MonoTypeEnum simple_type;
11011 mono_error_init (error);
11012 if ((p-buffer) + 10 >= *buflen) {
11015 newbuf = (char *)g_realloc (buffer, *buflen);
11016 p = newbuf + (p-buffer);
11020 argval = ((char*)arg + sizeof (MonoObject));
11021 simple_type = type->type;
11023 switch (simple_type) {
11024 case MONO_TYPE_BOOLEAN:
11029 case MONO_TYPE_CHAR:
11032 swap_with_size (p, argval, 2, 1);
11038 swap_with_size (p, argval, 4, 1);
11042 swap_with_size (p, argval, 8, 1);
11047 swap_with_size (p, argval, 8, 1);
11050 case MONO_TYPE_VALUETYPE:
11051 if (type->data.klass->enumtype) {
11052 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11055 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11058 case MONO_TYPE_STRING: {
11065 str = mono_string_to_utf8 ((MonoString*)arg);
11066 slen = strlen (str);
11067 if ((p-buffer) + 10 + slen >= *buflen) {
11071 newbuf = (char *)g_realloc (buffer, *buflen);
11072 p = newbuf + (p-buffer);
11075 mono_metadata_encode_value (slen, p, &p);
11076 memcpy (p, str, slen);
11081 case MONO_TYPE_CLASS: {
11084 MonoType *arg_type;
11090 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11091 return_if_nok (error);
11093 str = type_get_qualified_name (arg_type, NULL);
11094 slen = strlen (str);
11095 if ((p-buffer) + 10 + slen >= *buflen) {
11099 newbuf = (char *)g_realloc (buffer, *buflen);
11100 p = newbuf + (p-buffer);
11103 mono_metadata_encode_value (slen, p, &p);
11104 memcpy (p, str, slen);
11109 case MONO_TYPE_SZARRAY: {
11111 MonoClass *eclass, *arg_eclass;
11114 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11117 len = mono_array_length ((MonoArray*)arg);
11119 *p++ = (len >> 8) & 0xff;
11120 *p++ = (len >> 16) & 0xff;
11121 *p++ = (len >> 24) & 0xff;
11123 *retbuffer = buffer;
11124 eclass = type->data.klass;
11125 arg_eclass = mono_object_class (arg)->element_class;
11128 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11129 eclass = mono_defaults.object_class;
11131 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11132 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11133 int elsize = mono_class_array_element_size (arg_eclass);
11134 for (i = 0; i < len; ++i) {
11135 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11136 return_if_nok (error);
11139 } else if (eclass->valuetype && arg_eclass->valuetype) {
11140 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11141 int elsize = mono_class_array_element_size (eclass);
11142 for (i = 0; i < len; ++i) {
11143 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11144 return_if_nok (error);
11148 for (i = 0; i < len; ++i) {
11149 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11150 return_if_nok (error);
11155 case MONO_TYPE_OBJECT: {
11161 * The parameter type is 'object' but the type of the actual
11162 * argument is not. So we have to add type information to the blob
11163 * too. This is completely undocumented in the spec.
11167 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11172 klass = mono_object_class (arg);
11174 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11178 return_if_nok (error);
11181 if (klass->enumtype) {
11183 } else if (klass == mono_defaults.string_class) {
11184 simple_type = MONO_TYPE_STRING;
11187 } else if (klass->rank == 1) {
11189 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11190 /* See Partition II, Appendix B3 */
11193 *p++ = klass->element_class->byval_arg.type;
11194 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11195 return_if_nok (error);
11197 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11198 *p++ = simple_type = klass->byval_arg.type;
11201 g_error ("unhandled type in custom attr");
11203 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11204 slen = strlen (str);
11205 if ((p-buffer) + 10 + slen >= *buflen) {
11209 newbuf = (char *)g_realloc (buffer, *buflen);
11210 p = newbuf + (p-buffer);
11213 mono_metadata_encode_value (slen, p, &p);
11214 memcpy (p, str, slen);
11217 simple_type = mono_class_enum_basetype (klass)->type;
11221 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11224 *retbuffer = buffer;
11228 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11230 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11231 char *str = type_get_qualified_name (type, NULL);
11232 int slen = strlen (str);
11236 * This seems to be optional...
11239 mono_metadata_encode_value (slen, p, &p);
11240 memcpy (p, str, slen);
11243 } else if (type->type == MONO_TYPE_OBJECT) {
11245 } else if (type->type == MONO_TYPE_CLASS) {
11246 /* it should be a type: encode_cattr_value () has the check */
11249 mono_metadata_encode_value (type->type, p, &p);
11250 if (type->type == MONO_TYPE_SZARRAY)
11251 /* See the examples in Partition VI, Annex B */
11252 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11258 #ifndef DISABLE_REFLECTION_EMIT
11260 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11264 mono_error_init (error);
11266 /* Preallocate a large enough buffer */
11267 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11268 char *str = type_get_qualified_name (type, NULL);
11269 len = strlen (str);
11271 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11272 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11273 len = strlen (str);
11278 len += strlen (name);
11280 if ((p-buffer) + 20 + len >= *buflen) {
11284 newbuf = (char *)g_realloc (buffer, *buflen);
11285 p = newbuf + (p-buffer);
11289 encode_field_or_prop_type (type, p, &p);
11291 len = strlen (name);
11292 mono_metadata_encode_value (len, p, &p);
11293 memcpy (p, name, len);
11295 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11296 return_if_nok (error);
11298 *retbuffer = buffer;
11302 * mono_reflection_get_custom_attrs_blob:
11303 * @ctor: custom attribute constructor
11304 * @ctorArgs: arguments o the constructor
11310 * Creates the blob of data that needs to be saved in the metadata and that represents
11311 * the custom attributed described by @ctor, @ctorArgs etc.
11312 * Returns: a Byte array representing the blob of data.
11315 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11318 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11319 mono_error_cleanup (&error);
11324 * mono_reflection_get_custom_attrs_blob_checked:
11325 * @ctor: custom attribute constructor
11326 * @ctorArgs: arguments o the constructor
11331 * @error: set on error
11333 * Creates the blob of data that needs to be saved in the metadata and that represents
11334 * the custom attributed described by @ctor, @ctorArgs etc.
11335 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11338 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11340 MonoArray *result = NULL;
11341 MonoMethodSignature *sig;
11346 mono_error_init (error);
11348 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11349 /* sig is freed later so allocate it in the heap */
11350 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11351 if (!is_ok (error)) {
11356 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11359 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11361 p = buffer = (char *)g_malloc (buflen);
11362 /* write the prolog */
11365 for (i = 0; i < sig->param_count; ++i) {
11366 arg = mono_array_get (ctorArgs, MonoObject*, i);
11367 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11368 if (!is_ok (error)) goto leave;
11372 i += mono_array_length (properties);
11374 i += mono_array_length (fields);
11376 *p++ = (i >> 8) & 0xff;
11379 for (i = 0; i < mono_array_length (properties); ++i) {
11383 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11384 get_prop_name_and_type (prop, &pname, &ptype, error);
11385 if (!is_ok (error)) goto leave;
11386 *p++ = 0x54; /* PROPERTY signature */
11387 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11389 if (!is_ok (error)) goto leave;
11395 for (i = 0; i < mono_array_length (fields); ++i) {
11399 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11400 get_field_name_and_type (field, &fname, &ftype, error);
11401 if (!is_ok (error)) goto leave;
11402 *p++ = 0x53; /* FIELD signature */
11403 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11405 if (!is_ok (error)) goto leave;
11409 g_assert (p - buffer <= buflen);
11410 buflen = p - buffer;
11411 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11412 if (!is_ok (error))
11414 p = mono_array_addr (result, char, 0);
11415 memcpy (p, buffer, buflen);
11418 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11424 * reflection_setup_internal_class:
11425 * @tb: a TypeBuilder object
11426 * @error: set on error
11428 * Creates a MonoClass that represents the TypeBuilder.
11429 * This is a trick that lets us simplify a lot of reflection code
11430 * (and will allow us to support Build and Run assemblies easier).
11432 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11435 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11437 MonoClass *klass, *parent;
11439 mono_error_init (error);
11440 RESOLVE_TYPE (tb->parent, error);
11441 return_val_if_nok (error, FALSE);
11443 mono_loader_lock ();
11446 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11447 if (!is_ok (error)) {
11448 mono_loader_unlock ();
11451 /* check so we can compile corlib correctly */
11452 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11453 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11454 parent = parent_type->data.klass;
11456 parent = mono_class_from_mono_type (parent_type);
11462 /* the type has already being created: it means we just have to change the parent */
11463 if (tb->type.type) {
11464 klass = mono_class_from_mono_type (tb->type.type);
11465 klass->parent = NULL;
11466 /* fool mono_class_setup_parent */
11467 klass->supertypes = NULL;
11468 mono_class_setup_parent (klass, parent);
11469 mono_class_setup_mono_type (klass);
11470 mono_loader_unlock ();
11474 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11476 klass->image = &tb->module->dynamic_image->image;
11478 klass->inited = 1; /* we lie to the runtime */
11479 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11480 if (!is_ok (error))
11482 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11483 if (!is_ok (error))
11485 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11486 klass->flags = tb->attrs;
11488 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11490 klass->element_class = klass;
11492 if (mono_class_get_ref_info (klass) == NULL) {
11494 mono_class_set_ref_info (klass, tb);
11496 /* Put into cache so mono_class_get_checked () will find it.
11497 Skip nested types as those should not be available on the global scope. */
11498 if (!tb->nesting_type)
11499 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11502 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11503 by performing a mono_class_get which does the full resolution.
11505 Working around this semantics would require us to write a lot of code for no clear advantage.
11507 mono_image_append_class_to_reflection_info_set (klass);
11509 g_assert (mono_class_get_ref_info (klass) == tb);
11512 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11514 if (parent != NULL) {
11515 mono_class_setup_parent (klass, parent);
11516 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11517 const char *old_n = klass->name;
11518 /* trick to get relative numbering right when compiling corlib */
11519 klass->name = "BuildingObject";
11520 mono_class_setup_parent (klass, mono_defaults.object_class);
11521 klass->name = old_n;
11524 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11525 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11526 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11527 klass->instance_size = sizeof (MonoObject);
11528 klass->size_inited = 1;
11529 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11532 mono_class_setup_mono_type (klass);
11534 mono_class_setup_supertypes (klass);
11537 * FIXME: handle interfaces.
11540 tb->type.type = &klass->byval_arg;
11542 if (tb->nesting_type) {
11543 g_assert (tb->nesting_type->type);
11544 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11545 if (!is_ok (error)) goto failure;
11546 klass->nested_in = mono_class_from_mono_type (nesting_type);
11549 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11551 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11553 mono_loader_unlock ();
11557 mono_loader_unlock ();
11562 * mono_reflection_setup_internal_class:
11563 * @tb: a TypeBuilder object
11566 * Creates a MonoClass that represents the TypeBuilder.
11567 * This is a trick that lets us simplify a lot of reflection code
11568 * (and will allow us to support Build and Run assemblies easier).
11572 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11575 (void) reflection_setup_internal_class (tb, &error);
11576 mono_error_set_pending_exception (&error);
11580 * mono_reflection_setup_generic_class:
11581 * @tb: a TypeBuilder object
11583 * Setup the generic class before adding the first generic parameter.
11586 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11591 * mono_reflection_create_generic_class:
11592 * @tb: a TypeBuilder object
11593 * @error: set on error
11595 * Creates the generic class after all generic parameters have been added.
11596 * On success returns TRUE, on failure returns FALSE and sets @error.
11600 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11606 mono_error_init (error);
11608 klass = mono_class_from_mono_type (tb->type.type);
11610 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11612 if (klass->generic_container || (count == 0))
11615 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11617 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11619 klass->generic_container->owner.klass = klass;
11620 klass->generic_container->type_argc = count;
11621 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11623 klass->is_generic = 1;
11625 for (i = 0; i < count; i++) {
11626 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11627 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11628 return_val_if_nok (error, FALSE);
11629 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11630 klass->generic_container->type_params [i] = *param;
11631 /*Make sure we are a diferent type instance */
11632 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11633 klass->generic_container->type_params [i].info.pklass = NULL;
11634 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11636 g_assert (klass->generic_container->type_params [i].param.owner);
11639 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11644 * reflection_create_internal_class:
11645 * @tb: a TypeBuilder object
11646 * @error: set on error
11648 * Actually create the MonoClass that is associated with the TypeBuilder.
11649 * On success returns TRUE, on failure returns FALSE and sets @error.
11653 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11658 mono_error_init (error);
11659 klass = mono_class_from_mono_type (tb->type.type);
11661 mono_loader_lock ();
11662 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11663 MonoReflectionFieldBuilder *fb;
11665 MonoType *enum_basetype;
11667 g_assert (tb->fields != NULL);
11668 g_assert (mono_array_length (tb->fields) >= 1);
11670 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11672 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11673 if (!is_ok (error)) {
11674 mono_loader_unlock ();
11677 if (!mono_type_is_valid_enum_basetype (field_type)) {
11678 mono_loader_unlock ();
11682 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11683 if (!is_ok (error)) {
11684 mono_loader_unlock ();
11687 klass->element_class = mono_class_from_mono_type (enum_basetype);
11688 if (!klass->element_class)
11689 klass->element_class = mono_class_from_mono_type (enum_basetype);
11692 * get the element_class from the current corlib.
11694 ec = default_class_from_mono_type (enum_basetype);
11695 klass->instance_size = ec->instance_size;
11696 klass->size_inited = 1;
11698 * this is almost safe to do with enums and it's needed to be able
11699 * to create objects of the enum type (for use in SetConstant).
11701 /* FIXME: Does this mean enums can't have method overrides ? */
11702 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11704 mono_loader_unlock ();
11709 * mono_reflection_create_internal_class:
11710 * @tb: a TypeBuilder object
11713 * Actually create the MonoClass that is associated with the TypeBuilder.
11716 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11719 (void) reflection_create_internal_class (tb, &error);
11720 mono_error_set_pending_exception (&error);
11723 static MonoMarshalSpec*
11724 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11725 MonoReflectionMarshal *minfo, MonoError *error)
11727 MonoMarshalSpec *res;
11729 mono_error_init (error);
11731 res = image_g_new0 (image, MonoMarshalSpec, 1);
11732 res->native = (MonoMarshalNative)minfo->type;
11734 switch (minfo->type) {
11735 case MONO_NATIVE_LPARRAY:
11736 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11737 if (minfo->has_size) {
11738 res->data.array_data.param_num = minfo->param_num;
11739 res->data.array_data.num_elem = minfo->count;
11740 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11743 res->data.array_data.param_num = -1;
11744 res->data.array_data.num_elem = -1;
11745 res->data.array_data.elem_mult = -1;
11749 case MONO_NATIVE_BYVALTSTR:
11750 case MONO_NATIVE_BYVALARRAY:
11751 res->data.array_data.num_elem = minfo->count;
11754 case MONO_NATIVE_CUSTOM:
11755 if (minfo->marshaltyperef) {
11756 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11757 if (!is_ok (error)) {
11758 image_g_free (image, res);
11761 res->data.custom_data.custom_name =
11762 type_get_fully_qualified_name (marshaltyperef);
11764 if (minfo->mcookie)
11765 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11774 #endif /* !DISABLE_REFLECTION_EMIT */
11776 MonoReflectionMarshalAsAttribute*
11777 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11778 MonoMarshalSpec *spec, MonoError *error)
11780 MonoReflectionType *rt;
11781 MonoReflectionMarshalAsAttribute *minfo;
11784 mono_error_init (error);
11786 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11789 minfo->utype = spec->native;
11791 switch (minfo->utype) {
11792 case MONO_NATIVE_LPARRAY:
11793 minfo->array_subtype = spec->data.array_data.elem_type;
11794 minfo->size_const = spec->data.array_data.num_elem;
11795 if (spec->data.array_data.param_num != -1)
11796 minfo->size_param_index = spec->data.array_data.param_num;
11799 case MONO_NATIVE_BYVALTSTR:
11800 case MONO_NATIVE_BYVALARRAY:
11801 minfo->size_const = spec->data.array_data.num_elem;
11804 case MONO_NATIVE_CUSTOM:
11805 if (spec->data.custom_data.custom_name) {
11806 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11807 return_val_if_nok (error, NULL);
11810 rt = mono_type_get_object_checked (domain, mtype, error);
11814 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11817 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11819 if (spec->data.custom_data.cookie)
11820 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11830 #ifndef DISABLE_REFLECTION_EMIT
11832 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11833 ReflectionMethodBuilder *rmb,
11834 MonoMethodSignature *sig,
11838 MonoMethodWrapper *wrapperm;
11839 MonoMarshalSpec **specs;
11840 MonoReflectionMethodAux *method_aux;
11845 mono_error_init (error);
11847 * Methods created using a MethodBuilder should have their memory allocated
11848 * inside the image mempool, while dynamic methods should have their memory
11851 dynamic = rmb->refs != NULL;
11852 image = dynamic ? NULL : klass->image;
11855 g_assert (!klass->generic_class);
11857 mono_loader_lock ();
11859 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11860 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11861 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11863 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11865 wrapperm = (MonoMethodWrapper*)m;
11867 m->dynamic = dynamic;
11869 m->flags = rmb->attrs;
11870 m->iflags = rmb->iattrs;
11871 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11873 m->signature = sig;
11874 m->sre_method = TRUE;
11875 m->skip_visibility = rmb->skip_visibility;
11876 if (rmb->table_idx)
11877 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11879 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11880 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11881 m->string_ctor = 1;
11883 m->signature->pinvoke = 1;
11884 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11885 m->signature->pinvoke = 1;
11887 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11889 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11890 mono_error_assert_ok (error);
11891 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11892 mono_error_assert_ok (error);
11894 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11896 if (image_is_dynamic (klass->image))
11897 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11899 mono_loader_unlock ();
11902 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11903 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11904 MonoMethodHeader *header;
11906 gint32 max_stack, i;
11907 gint32 num_locals = 0;
11908 gint32 num_clauses = 0;
11912 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11913 code_size = rmb->ilgen->code_len;
11914 max_stack = rmb->ilgen->max_stack;
11915 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11916 if (rmb->ilgen->ex_handlers)
11917 num_clauses = method_count_clauses (rmb->ilgen);
11920 code = mono_array_addr (rmb->code, guint8, 0);
11921 code_size = mono_array_length (rmb->code);
11922 /* we probably need to run a verifier on the code... */
11932 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11933 header->code_size = code_size;
11934 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11935 memcpy ((char*)header->code, code, code_size);
11936 header->max_stack = max_stack;
11937 header->init_locals = rmb->init_locals;
11938 header->num_locals = num_locals;
11940 for (i = 0; i < num_locals; ++i) {
11941 MonoReflectionLocalBuilder *lb =
11942 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11944 header->locals [i] = image_g_new0 (image, MonoType, 1);
11945 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
11946 mono_error_assert_ok (error);
11947 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11950 header->num_clauses = num_clauses;
11952 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11953 rmb->ilgen, num_clauses, error);
11954 mono_error_assert_ok (error);
11957 wrapperm->header = header;
11960 if (rmb->generic_params) {
11961 int count = mono_array_length (rmb->generic_params);
11962 MonoGenericContainer *container = rmb->generic_container;
11964 g_assert (container);
11966 container->type_argc = count;
11967 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11968 container->owner.method = m;
11969 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11971 m->is_generic = TRUE;
11972 mono_method_set_generic_container (m, container);
11974 for (i = 0; i < count; i++) {
11975 MonoReflectionGenericParam *gp =
11976 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11977 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
11978 mono_error_assert_ok (error);
11979 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11980 container->type_params [i] = *param;
11984 * The method signature might have pointers to generic parameters that belong to other methods.
11985 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11986 * generic parameters.
11988 for (i = 0; i < m->signature->param_count; ++i) {
11989 MonoType *t = m->signature->params [i];
11990 if (t->type == MONO_TYPE_MVAR) {
11991 MonoGenericParam *gparam = t->data.generic_param;
11992 if (gparam->num < count) {
11993 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11994 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12000 if (klass->generic_container) {
12001 container->parent = klass->generic_container;
12002 container->context.class_inst = klass->generic_container->context.class_inst;
12004 container->context.method_inst = mono_get_shared_generic_inst (container);
12008 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12012 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12014 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12015 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12016 for (i = 0; i < rmb->nrefs; ++i)
12017 data [i + 1] = rmb->refs [i];
12022 /* Parameter info */
12025 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12026 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12027 for (i = 0; i <= m->signature->param_count; ++i) {
12028 MonoReflectionParamBuilder *pb;
12029 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12030 if ((i > 0) && (pb->attrs)) {
12031 /* Make a copy since it might point to a shared type structure */
12032 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12033 m->signature->params [i - 1]->attrs = pb->attrs;
12036 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12037 MonoDynamicImage *assembly;
12039 MonoTypeEnum def_type;
12043 if (!method_aux->param_defaults) {
12044 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12045 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12047 assembly = (MonoDynamicImage*)klass->image;
12048 idx = encode_constant (assembly, pb->def_value, &def_type);
12049 /* Copy the data from the blob since it might get realloc-ed */
12050 p = assembly->blob.data + idx;
12051 len = mono_metadata_decode_blob_size (p, &p2);
12053 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12054 method_aux->param_default_types [i] = def_type;
12055 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12059 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12060 mono_error_assert_ok (error);
12063 if (!method_aux->param_cattr)
12064 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12065 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12071 /* Parameter marshalling */
12074 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12075 MonoReflectionParamBuilder *pb;
12076 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12077 if (pb->marshal_info) {
12079 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12080 specs [pb->position] =
12081 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12082 if (!is_ok (error)) {
12083 mono_loader_unlock ();
12084 image_g_free (image, specs);
12085 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12091 if (specs != NULL) {
12093 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12094 method_aux->param_marshall = specs;
12097 if (image_is_dynamic (klass->image) && method_aux)
12098 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12100 mono_loader_unlock ();
12106 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12108 ReflectionMethodBuilder rmb;
12109 MonoMethodSignature *sig;
12111 mono_loader_lock ();
12112 g_assert (klass->image != NULL);
12113 sig = ctor_builder_to_signature (klass->image, mb, error);
12114 mono_loader_unlock ();
12115 return_val_if_nok (error, NULL);
12117 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12120 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12121 return_val_if_nok (error, NULL);
12122 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12124 /* If we are in a generic class, we might be called multiple times from inflate_method */
12125 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12126 /* ilgen is no longer needed */
12130 return mb->mhandle;
12134 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12136 ReflectionMethodBuilder rmb;
12137 MonoMethodSignature *sig;
12139 mono_error_init (error);
12141 mono_loader_lock ();
12142 g_assert (klass->image != NULL);
12143 sig = method_builder_to_signature (klass->image, mb, error);
12144 mono_loader_unlock ();
12145 return_val_if_nok (error, NULL);
12147 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12150 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12151 return_val_if_nok (error, NULL);
12152 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12154 /* If we are in a generic class, we might be called multiple times from inflate_method */
12155 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12156 /* ilgen is no longer needed */
12159 return mb->mhandle;
12162 static MonoClassField*
12163 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12165 MonoClassField *field;
12168 mono_error_init (error);
12170 field = g_new0 (MonoClassField, 1);
12172 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12173 mono_error_assert_ok (error);
12174 if (fb->attrs || fb->modreq || fb->modopt) {
12175 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12176 if (!is_ok (error)) {
12180 field->type = mono_metadata_type_dup (NULL, type);
12181 field->type->attrs = fb->attrs;
12183 g_assert (image_is_dynamic (klass->image));
12184 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12185 g_free (field->type);
12186 if (!is_ok (error)) {
12190 field->type = mono_metadata_type_dup (klass->image, custom);
12193 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12194 if (!is_ok (error)) {
12199 if (fb->offset != -1)
12200 field->offset = fb->offset;
12201 field->parent = klass;
12202 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12204 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12211 * mono_reflection_bind_generic_parameters:
12212 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12213 * @type_args: the number of type arguments to bind
12214 * @types: array of type arguments
12215 * @error: set on error
12217 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12218 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12221 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12224 MonoReflectionTypeBuilder *tb = NULL;
12225 gboolean is_dynamic = FALSE;
12226 MonoClass *geninst;
12228 mono_error_init (error);
12230 mono_loader_lock ();
12232 if (is_sre_type_builder (mono_object_class (type))) {
12233 tb = (MonoReflectionTypeBuilder *) type;
12236 } else if (is_sre_generic_instance (mono_object_class (type))) {
12237 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12238 MonoReflectionType *gtd = rgi->generic_type;
12240 if (is_sre_type_builder (mono_object_class (gtd))) {
12241 tb = (MonoReflectionTypeBuilder *)gtd;
12246 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12247 if (tb && tb->generic_container) {
12248 if (!mono_reflection_create_generic_class (tb, error)) {
12249 mono_loader_unlock ();
12254 MonoType *t = mono_reflection_type_get_handle (type, error);
12255 if (!is_ok (error)) {
12256 mono_loader_unlock ();
12260 klass = mono_class_from_mono_type (t);
12261 if (!klass->generic_container) {
12262 mono_loader_unlock ();
12263 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12267 if (klass->wastypebuilder) {
12268 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12273 mono_loader_unlock ();
12275 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12277 return &geninst->byval_arg;
12281 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12283 MonoGenericClass *gclass;
12284 MonoGenericInst *inst;
12286 g_assert (klass->generic_container);
12288 inst = mono_metadata_get_generic_inst (type_argc, types);
12289 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12291 return mono_generic_class_get_class (gclass);
12294 static MonoReflectionMethod*
12295 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12298 MonoMethod *method, *inflated;
12299 MonoMethodInflated *imethod;
12300 MonoGenericContext tmp_context;
12301 MonoGenericInst *ginst;
12302 MonoType **type_argv;
12305 mono_error_init (error);
12307 /*FIXME but this no longer should happen*/
12308 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12309 #ifndef DISABLE_REFLECTION_EMIT
12310 MonoReflectionMethodBuilder *mb = NULL;
12314 mb = (MonoReflectionMethodBuilder *) rmethod;
12315 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12316 return_val_if_nok (error, NULL);
12317 klass = mono_class_from_mono_type (tb);
12319 method = methodbuilder_to_mono_method (klass, mb, error);
12320 return_val_if_nok (error, NULL);
12322 g_assert_not_reached ();
12326 method = rmethod->method;
12329 klass = method->klass;
12331 if (method->is_inflated)
12332 method = ((MonoMethodInflated *) method)->declaring;
12334 count = mono_method_signature (method)->generic_param_count;
12335 if (count != mono_array_length (types))
12338 type_argv = g_new0 (MonoType *, count);
12339 for (i = 0; i < count; i++) {
12340 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12341 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12342 if (!is_ok (error)) {
12343 g_free (type_argv);
12347 ginst = mono_metadata_get_generic_inst (count, type_argv);
12348 g_free (type_argv);
12350 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12351 tmp_context.method_inst = ginst;
12353 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12354 mono_error_assert_ok (error);
12355 imethod = (MonoMethodInflated *) inflated;
12357 /*FIXME but I think this is no longer necessary*/
12358 if (image_is_dynamic (method->klass->image)) {
12359 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12361 * This table maps metadata structures representing inflated methods/fields
12362 * to the reflection objects representing their generic definitions.
12364 mono_image_lock ((MonoImage*)image);
12365 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12366 mono_image_unlock ((MonoImage*)image);
12369 if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12370 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12374 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12378 MonoReflectionMethod*
12379 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12382 MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12383 mono_error_set_pending_exception (&error);
12388 #ifndef DISABLE_REFLECTION_EMIT
12390 static MonoMethod *
12391 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12393 MonoMethodInflated *imethod;
12394 MonoGenericContext *context;
12398 * With generic code sharing the klass might not be inflated.
12399 * This can happen because classes inflated with their own
12400 * type arguments are "normalized" to the uninflated class.
12402 if (!klass->generic_class)
12405 context = mono_class_get_context (klass);
12407 if (klass->method.count && klass->methods) {
12408 /* Find the already created inflated method */
12409 for (i = 0; i < klass->method.count; ++i) {
12410 g_assert (klass->methods [i]->is_inflated);
12411 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12414 g_assert (i < klass->method.count);
12415 imethod = (MonoMethodInflated*)klass->methods [i];
12418 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12419 mono_error_assert_ok (&error);
12422 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12423 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12425 mono_image_lock ((MonoImage*)image);
12426 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12427 mono_image_unlock ((MonoImage*)image);
12429 return (MonoMethod *) imethod;
12432 static MonoMethod *
12433 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12435 MonoMethod *method;
12438 mono_error_init (error);
12440 MonoClass *type_class = mono_object_class (type);
12442 if (is_sre_generic_instance (type_class)) {
12443 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12444 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12445 return_val_if_nok (error, NULL);
12446 gklass = mono_class_from_mono_type (generic_type);
12447 } else if (is_sre_type_builder (type_class)) {
12448 MonoType *t = mono_reflection_type_get_handle (type, error);
12449 return_val_if_nok (error, NULL);
12450 gklass = mono_class_from_mono_type (t);
12451 } else if (type->type) {
12452 gklass = mono_class_from_mono_type (type->type);
12453 gklass = mono_class_get_generic_type_definition (gklass);
12455 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12458 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12459 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12460 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12462 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12466 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12467 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12470 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12471 method = ((MonoReflectionMethod *) obj)->method;
12473 method = NULL; /* prevent compiler warning */
12474 g_error ("can't handle type %s", obj->vtable->klass->name);
12477 MonoType *t = mono_reflection_type_get_handle (type, error);
12478 return_val_if_nok (error, NULL);
12479 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12482 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12484 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12486 MonoGenericClass *gclass;
12487 MonoDynamicGenericClass *dgclass;
12488 MonoClass *klass, *gklass;
12492 mono_error_init (error);
12494 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12495 return_val_if_nok (error, FALSE);
12496 klass = mono_class_from_mono_type (gtype);
12497 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12498 gclass = gtype->data.generic_class;
12500 if (!gclass->is_dynamic)
12503 dgclass = (MonoDynamicGenericClass *) gclass;
12505 if (dgclass->initialized)
12508 gklass = gclass->container_class;
12509 mono_class_init (gklass);
12511 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12513 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12514 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12515 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12517 for (i = 0; i < dgclass->count_fields; i++) {
12518 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12519 MonoClassField *field, *inflated_field = NULL;
12521 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12522 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12523 return_val_if_nok (error, FALSE);
12524 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12525 field = ((MonoReflectionField *) obj)->field;
12527 field = NULL; /* prevent compiler warning */
12528 g_assert_not_reached ();
12531 dgclass->fields [i] = *field;
12532 dgclass->fields [i].parent = klass;
12533 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12534 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12535 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12536 dgclass->field_generic_types [i] = field->type;
12537 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12538 dgclass->field_objects [i] = obj;
12540 if (inflated_field) {
12541 g_free (inflated_field);
12543 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12547 dgclass->initialized = TRUE;
12552 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12555 (void) reflection_generic_class_initialize (type, fields, &error);
12556 mono_error_set_pending_exception (&error);
12560 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12562 MonoDynamicGenericClass *dgclass;
12565 g_assert (gclass->is_dynamic);
12567 dgclass = (MonoDynamicGenericClass *)gclass;
12569 for (i = 0; i < dgclass->count_fields; ++i) {
12570 MonoClassField *field = dgclass->fields + i;
12571 mono_metadata_free_type (field->type);
12572 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12577 * fix_partial_generic_class:
12578 * @klass: a generic instantiation MonoClass
12579 * @error: set on error
12581 * Assumes that the generic container of @klass has its vtable
12582 * initialized, and updates the parent class, insterfaces, methods and
12583 * fields of @klass by inflating the types using the generic context.
12585 * On success returns TRUE, on failure returns FALSE and sets @error.
12589 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12591 MonoClass *gklass = klass->generic_class->container_class;
12592 MonoDynamicGenericClass *dgclass;
12595 mono_error_init (error);
12597 if (klass->wastypebuilder)
12600 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12601 if (klass->parent != gklass->parent) {
12602 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12603 if (mono_error_ok (error)) {
12604 MonoClass *parent = mono_class_from_mono_type (parent_type);
12605 mono_metadata_free_type (parent_type);
12606 if (parent != klass->parent) {
12607 /*fool mono_class_setup_parent*/
12608 klass->supertypes = NULL;
12609 mono_class_setup_parent (klass, parent);
12612 if (gklass->wastypebuilder)
12613 klass->wastypebuilder = TRUE;
12618 if (!dgclass->initialized)
12621 if (klass->method.count != gklass->method.count) {
12622 klass->method.count = gklass->method.count;
12623 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12625 for (i = 0; i < klass->method.count; i++) {
12626 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12627 gklass->methods [i], klass, mono_class_get_context (klass), error);
12628 mono_error_assert_ok (error);
12632 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12633 klass->interface_count = gklass->interface_count;
12634 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12635 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12637 for (i = 0; i < gklass->interface_count; ++i) {
12638 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12639 return_val_if_nok (error, FALSE);
12641 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12642 mono_metadata_free_type (iface_type);
12644 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12647 klass->interfaces_inited = 1;
12650 if (klass->field.count != gklass->field.count) {
12651 klass->field.count = gklass->field.count;
12652 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12654 for (i = 0; i < klass->field.count; i++) {
12655 klass->fields [i] = gklass->fields [i];
12656 klass->fields [i].parent = klass;
12657 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12658 return_val_if_nok (error, FALSE);
12662 /*We can only finish with this klass once it's parent has as well*/
12663 if (gklass->wastypebuilder)
12664 klass->wastypebuilder = TRUE;
12669 * ensure_generic_class_runtime_vtable:
12670 * @klass a generic class
12671 * @error set on error
12673 * Ensures that the generic container of @klass has a vtable and
12674 * returns TRUE on success. On error returns FALSE and sets @error.
12677 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12679 MonoClass *gklass = klass->generic_class->container_class;
12681 mono_error_init (error);
12683 if (!ensure_runtime_vtable (gklass, error))
12686 return fix_partial_generic_class (klass, error);
12690 * ensure_runtime_vtable:
12692 * @error set on error
12694 * Ensures that @klass has a vtable and returns TRUE on success. On
12695 * error returns FALSE and sets @error.
12698 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12700 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12703 mono_error_init (error);
12705 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12708 if (!ensure_runtime_vtable (klass->parent, error))
12712 num = tb->ctors? mono_array_length (tb->ctors): 0;
12713 num += tb->num_methods;
12714 klass->method.count = num;
12715 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12716 num = tb->ctors? mono_array_length (tb->ctors): 0;
12717 for (i = 0; i < num; ++i) {
12718 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12721 klass->methods [i] = ctor;
12723 num = tb->num_methods;
12725 for (i = 0; i < num; ++i) {
12726 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12729 klass->methods [j++] = meth;
12732 if (tb->interfaces) {
12733 klass->interface_count = mono_array_length (tb->interfaces);
12734 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12735 for (i = 0; i < klass->interface_count; ++i) {
12736 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12737 return_val_if_nok (error, FALSE);
12738 klass->interfaces [i] = mono_class_from_mono_type (iface);
12739 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12742 klass->interfaces_inited = 1;
12744 } else if (klass->generic_class){
12745 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12746 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12751 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12753 for (i = 0; i < klass->method.count; ++i) {
12754 MonoMethod *im = klass->methods [i];
12755 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12756 im->slot = slot_num++;
12759 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12760 mono_class_setup_interface_offsets (klass);
12761 mono_class_setup_interface_id (klass);
12765 * The generic vtable is needed even if image->run is not set since some
12766 * runtime code like ves_icall_Type_GetMethodsByName depends on
12767 * method->slot being defined.
12771 * tb->methods could not be freed since it is used for determining
12772 * overrides during dynamic vtable construction.
12779 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12781 mono_error_init (error);
12782 MonoClass *klass = mono_object_class (method);
12783 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12784 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12785 return sr_method->method;
12787 if (is_sre_method_builder (klass)) {
12788 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12789 return mb->mhandle;
12791 if (is_sre_method_on_tb_inst (klass)) {
12792 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12793 MonoMethod *result;
12794 /*FIXME move this to a proper method and unify with resolve_object*/
12795 if (m->method_args) {
12796 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12798 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12799 return_val_if_nok (error, NULL);
12800 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12801 MonoMethod *mono_method;
12803 if (is_sre_method_builder (mono_object_class (m->mb)))
12804 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12805 else if (is_sr_mono_method (mono_object_class (m->mb)))
12806 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12808 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)));
12810 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12815 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12820 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12822 MonoReflectionTypeBuilder *tb;
12824 MonoReflectionMethod *m;
12826 mono_error_init (error);
12828 *num_overrides = 0;
12830 g_assert (image_is_dynamic (klass->image));
12832 if (!mono_class_get_ref_info (klass))
12835 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12837 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12841 for (i = 0; i < tb->num_methods; ++i) {
12842 MonoReflectionMethodBuilder *mb =
12843 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12844 if (mb->override_methods)
12845 onum += mono_array_length (mb->override_methods);
12850 *overrides = g_new0 (MonoMethod*, onum * 2);
12853 for (i = 0; i < tb->num_methods; ++i) {
12854 MonoReflectionMethodBuilder *mb =
12855 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12856 if (mb->override_methods) {
12857 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12858 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12860 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12861 return_if_nok (error);
12862 (*overrides) [onum * 2 + 1] = mb->mhandle;
12864 g_assert (mb->mhandle);
12872 *num_overrides = onum;
12876 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12878 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12879 MonoReflectionFieldBuilder *fb;
12880 MonoClassField *field;
12881 MonoImage *image = klass->image;
12882 const char *p, *p2;
12884 guint32 len, idx, real_size = 0;
12886 klass->field.count = tb->num_fields;
12887 klass->field.first = 0;
12889 mono_error_init (error);
12891 if (tb->class_size) {
12892 if ((tb->packing_size & 0xffffff00) != 0) {
12893 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12894 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12897 klass->packing_size = tb->packing_size;
12898 real_size = klass->instance_size + tb->class_size;
12901 if (!klass->field.count) {
12902 klass->instance_size = MAX (klass->instance_size, real_size);
12906 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12907 mono_class_alloc_ext (klass);
12908 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12910 This is, guess what, a hack.
12911 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12912 On the static path no field class is resolved, only types are built. This is the right thing to do
12914 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12916 klass->size_inited = 1;
12918 for (i = 0; i < klass->field.count; ++i) {
12919 MonoArray *rva_data;
12920 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12921 field = &klass->fields [i];
12922 field->name = mono_string_to_utf8_image (image, fb->name, error);
12923 if (!mono_error_ok (error))
12926 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12927 return_if_nok (error);
12928 field->type = mono_metadata_type_dup (klass->image, type);
12929 field->type->attrs = fb->attrs;
12931 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12932 return_if_nok (error);
12935 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12936 char *base = mono_array_addr (rva_data, char, 0);
12937 size_t size = mono_array_length (rva_data);
12938 char *data = (char *)mono_image_alloc (klass->image, size);
12939 memcpy (data, base, size);
12940 klass->ext->field_def_values [i].data = data;
12942 if (fb->offset != -1)
12943 field->offset = fb->offset;
12944 field->parent = klass;
12945 fb->handle = field;
12946 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12948 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12949 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12951 if (fb->def_value) {
12952 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12953 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12954 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12955 /* Copy the data from the blob since it might get realloc-ed */
12956 p = assembly->blob.data + idx;
12957 len = mono_metadata_decode_blob_size (p, &p2);
12959 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12960 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12964 klass->instance_size = MAX (klass->instance_size, real_size);
12965 mono_class_layout_fields (klass, klass->instance_size);
12969 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12971 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12972 MonoReflectionPropertyBuilder *pb;
12973 MonoImage *image = klass->image;
12974 MonoProperty *properties;
12977 mono_error_init (error);
12980 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12982 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12983 klass->ext->property.first = 0;
12985 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12986 klass->ext->properties = properties;
12987 for (i = 0; i < klass->ext->property.count; ++i) {
12988 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12989 properties [i].parent = klass;
12990 properties [i].attrs = pb->attrs;
12991 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12992 if (!mono_error_ok (error))
12994 if (pb->get_method)
12995 properties [i].get = pb->get_method->mhandle;
12996 if (pb->set_method)
12997 properties [i].set = pb->set_method->mhandle;
12999 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13000 if (pb->def_value) {
13002 const char *p, *p2;
13003 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13004 if (!klass->ext->prop_def_values)
13005 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13006 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13007 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13008 /* Copy the data from the blob since it might get realloc-ed */
13009 p = assembly->blob.data + idx;
13010 len = mono_metadata_decode_blob_size (p, &p2);
13012 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13013 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13018 static MonoReflectionEvent *
13019 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13021 mono_error_init (error);
13023 MonoEvent *event = g_new0 (MonoEvent, 1);
13026 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13027 if (!is_ok (error)) {
13031 klass = mono_class_from_mono_type (type);
13033 event->parent = klass;
13034 event->attrs = eb->attrs;
13035 event->name = mono_string_to_utf8 (eb->name);
13036 if (eb->add_method)
13037 event->add = eb->add_method->mhandle;
13038 if (eb->remove_method)
13039 event->remove = eb->remove_method->mhandle;
13040 if (eb->raise_method)
13041 event->raise = eb->raise_method->mhandle;
13043 #ifndef MONO_SMALL_CONFIG
13044 if (eb->other_methods) {
13046 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13047 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13048 MonoReflectionMethodBuilder *mb =
13049 mono_array_get (eb->other_methods,
13050 MonoReflectionMethodBuilder*, j);
13051 event->other [j] = mb->mhandle;
13056 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13057 if (!is_ok (error)) {
13058 #ifndef MONO_SMALL_CONFIG
13059 g_free (event->other);
13067 MonoReflectionEvent *
13068 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13071 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13072 mono_error_set_pending_exception (&error);
13077 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13079 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13080 MonoReflectionEventBuilder *eb;
13081 MonoImage *image = klass->image;
13085 mono_error_init (error);
13088 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13090 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13091 klass->ext->event.first = 0;
13093 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13094 klass->ext->events = events;
13095 for (i = 0; i < klass->ext->event.count; ++i) {
13096 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13097 events [i].parent = klass;
13098 events [i].attrs = eb->attrs;
13099 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13100 if (!mono_error_ok (error))
13102 if (eb->add_method)
13103 events [i].add = eb->add_method->mhandle;
13104 if (eb->remove_method)
13105 events [i].remove = eb->remove_method->mhandle;
13106 if (eb->raise_method)
13107 events [i].raise = eb->raise_method->mhandle;
13109 #ifndef MONO_SMALL_CONFIG
13110 if (eb->other_methods) {
13112 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13113 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13114 MonoReflectionMethodBuilder *mb =
13115 mono_array_get (eb->other_methods,
13116 MonoReflectionMethodBuilder*, j);
13117 events [i].other [j] = mb->mhandle;
13121 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13125 struct remove_instantiations_user_data
13132 remove_instantiations_of_and_ensure_contents (gpointer key,
13134 gpointer user_data)
13136 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13137 MonoType *type = (MonoType*)key;
13138 MonoClass *klass = data->klass;
13139 gboolean already_failed = !is_ok (data->error);
13141 MonoError *error = already_failed ? &lerror : data->error;
13143 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13144 MonoClass *inst_klass = mono_class_from_mono_type (type);
13145 //Ensure it's safe to use it.
13146 if (!fix_partial_generic_class (inst_klass, error)) {
13147 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13148 // Marked the class with failure, but since some other instantiation already failed,
13149 // just report that one, and swallow the error from this one.
13150 if (already_failed)
13151 mono_error_cleanup (error);
13159 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13161 mono_error_init (error);
13167 for (i = 0; i < mono_array_length (arr); ++i) {
13168 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13169 if (!mono_error_ok (error))
13174 MonoReflectionType*
13175 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13179 MonoDomain* domain;
13180 MonoReflectionType* res;
13183 mono_error_init (&error);
13185 domain = mono_object_domain (tb);
13186 klass = mono_class_from_mono_type (tb->type.type);
13189 * Check for user defined Type subclasses.
13191 RESOLVE_TYPE (tb->parent, &error);
13192 if (!is_ok (&error))
13193 goto failure_unlocked;
13194 check_array_for_usertypes (tb->interfaces, &error);
13195 if (!is_ok (&error))
13196 goto failure_unlocked;
13198 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13199 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13201 RESOLVE_TYPE (fb->type, &error);
13202 if (!is_ok (&error))
13203 goto failure_unlocked;
13204 check_array_for_usertypes (fb->modreq, &error);
13205 if (!is_ok (&error))
13206 goto failure_unlocked;
13207 check_array_for_usertypes (fb->modopt, &error);
13208 if (!is_ok (&error))
13209 goto failure_unlocked;
13210 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13211 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13212 if (!is_ok (&error))
13213 goto failure_unlocked;
13219 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13220 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13222 RESOLVE_TYPE (mb->rtype, &error);
13223 if (!is_ok (&error))
13224 goto failure_unlocked;
13225 check_array_for_usertypes (mb->return_modreq, &error);
13226 if (!is_ok (&error))
13227 goto failure_unlocked;
13228 check_array_for_usertypes (mb->return_modopt, &error);
13229 if (!is_ok (&error))
13230 goto failure_unlocked;
13231 check_array_for_usertypes (mb->parameters, &error);
13232 if (!is_ok (&error))
13233 goto failure_unlocked;
13234 if (mb->param_modreq)
13235 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13236 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13237 if (!is_ok (&error))
13238 goto failure_unlocked;
13240 if (mb->param_modopt)
13241 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13242 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13243 if (!is_ok (&error))
13244 goto failure_unlocked;
13250 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13251 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13253 check_array_for_usertypes (mb->parameters, &error);
13254 if (!is_ok (&error))
13255 goto failure_unlocked;
13256 if (mb->param_modreq)
13257 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13258 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13259 if (!is_ok (&error))
13260 goto failure_unlocked;
13262 if (mb->param_modopt)
13263 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13264 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13265 if (!is_ok (&error))
13266 goto failure_unlocked;
13272 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13275 * we need to lock the domain because the lock will be taken inside
13276 * So, we need to keep the locking order correct.
13278 mono_loader_lock ();
13279 mono_domain_lock (domain);
13280 if (klass->wastypebuilder) {
13281 mono_domain_unlock (domain);
13282 mono_loader_unlock ();
13284 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13285 mono_error_set_pending_exception (&error);
13290 * Fields to set in klass:
13291 * the various flags: delegate/unicode/contextbound etc.
13293 klass->flags = tb->attrs;
13294 klass->has_cctor = 1;
13296 mono_class_setup_parent (klass, klass->parent);
13297 /* fool mono_class_setup_supertypes */
13298 klass->supertypes = NULL;
13299 mono_class_setup_supertypes (klass);
13300 mono_class_setup_mono_type (klass);
13303 if (!((MonoDynamicImage*)klass->image)->run) {
13304 if (klass->generic_container) {
13305 /* FIXME: The code below can't handle generic classes */
13306 klass->wastypebuilder = TRUE;
13307 mono_loader_unlock ();
13308 mono_domain_unlock (domain);
13310 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13311 mono_error_set_pending_exception (&error);
13318 /* enums are done right away */
13319 if (!klass->enumtype)
13320 if (!ensure_runtime_vtable (klass, &error))
13323 if (tb->subtypes) {
13324 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13325 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13326 mono_class_alloc_ext (klass);
13327 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13328 if (!is_ok (&error)) goto failure;
13329 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13333 klass->nested_classes_inited = TRUE;
13335 /* fields and object layout */
13336 if (klass->parent) {
13337 if (!klass->parent->size_inited)
13338 mono_class_init (klass->parent);
13339 klass->instance_size = klass->parent->instance_size;
13340 klass->sizes.class_size = 0;
13341 klass->min_align = klass->parent->min_align;
13342 /* if the type has no fields we won't call the field_setup
13343 * routine which sets up klass->has_references.
13345 klass->has_references |= klass->parent->has_references;
13347 klass->instance_size = sizeof (MonoObject);
13348 klass->min_align = 1;
13351 /* FIXME: handle packing_size and instance_size */
13352 typebuilder_setup_fields (klass, &error);
13353 if (!mono_error_ok (&error))
13355 typebuilder_setup_properties (klass, &error);
13356 if (!mono_error_ok (&error))
13359 typebuilder_setup_events (klass, &error);
13360 if (!mono_error_ok (&error))
13363 klass->wastypebuilder = TRUE;
13366 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13367 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13368 * we want to return normal System.MonoType objects, so clear these out from the cache.
13370 * Together with this we must ensure the contents of all instances to match the created type.
13372 if (domain->type_hash && klass->generic_container) {
13373 struct remove_instantiations_user_data data;
13374 data.klass = klass;
13375 data.error = &error;
13376 mono_error_assert_ok (&error);
13377 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13378 if (!is_ok (&error))
13382 mono_domain_unlock (domain);
13383 mono_loader_unlock ();
13385 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13386 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13387 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13388 goto failure_unlocked;
13391 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13392 if (!is_ok (&error))
13393 goto failure_unlocked;
13395 g_assert (res != (MonoReflectionType*)tb);
13400 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13401 klass->wastypebuilder = TRUE;
13402 mono_domain_unlock (domain);
13403 mono_loader_unlock ();
13405 mono_error_set_pending_exception (&error);
13410 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13412 MonoGenericParamFull *param;
13416 mono_error_init (error);
13418 image = &gparam->tbuilder->module->dynamic_image->image;
13420 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13422 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13423 mono_error_assert_ok (error);
13424 param->param.num = gparam->index;
13426 if (gparam->mbuilder) {
13427 if (!gparam->mbuilder->generic_container) {
13428 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13429 return_val_if_nok (error, FALSE);
13431 MonoClass *klass = mono_class_from_mono_type (tb);
13432 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13433 gparam->mbuilder->generic_container->is_method = TRUE;
13435 * Cannot set owner.method, since the MonoMethod is not created yet.
13436 * Set the image field instead, so type_in_image () works.
13438 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13439 gparam->mbuilder->generic_container->owner.image = klass->image;
13441 param->param.owner = gparam->mbuilder->generic_container;
13442 } else if (gparam->tbuilder) {
13443 if (!gparam->tbuilder->generic_container) {
13444 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13445 return_val_if_nok (error, FALSE);
13446 MonoClass *klass = mono_class_from_mono_type (tb);
13447 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13448 gparam->tbuilder->generic_container->owner.klass = klass;
13450 param->param.owner = gparam->tbuilder->generic_container;
13453 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13455 gparam->type.type = &pklass->byval_arg;
13457 mono_class_set_ref_info (pklass, gparam);
13458 mono_image_append_class_to_reflection_info_set (pklass);
13464 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13467 (void) reflection_initialize_generic_parameter (gparam, &error);
13468 mono_error_set_pending_exception (&error);
13473 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13475 MonoReflectionModuleBuilder *module = sig->module;
13476 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13477 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13482 mono_error_init (error);
13484 check_array_for_usertypes (sig->arguments, error);
13485 return_val_if_nok (error, NULL);
13487 sigbuffer_init (&buf, 32);
13489 sigbuffer_add_value (&buf, 0x07);
13490 sigbuffer_add_value (&buf, na);
13491 if (assembly != NULL){
13492 for (i = 0; i < na; ++i) {
13493 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13494 encode_reflection_type (assembly, type, &buf, error);
13495 if (!is_ok (error)) goto fail;
13499 buflen = buf.p - buf.buf;
13500 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13501 if (!is_ok (error)) goto fail;
13502 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13503 sigbuffer_free (&buf);
13506 sigbuffer_free (&buf);
13511 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13514 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13515 mono_error_set_pending_exception (&error);
13520 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13522 MonoDynamicImage *assembly = sig->module->dynamic_image;
13523 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13528 mono_error_init (error);
13530 check_array_for_usertypes (sig->arguments, error);
13531 return_val_if_nok (error, NULL);
13533 sigbuffer_init (&buf, 32);
13535 sigbuffer_add_value (&buf, 0x06);
13536 for (i = 0; i < na; ++i) {
13537 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13538 encode_reflection_type (assembly, type, &buf, error);
13539 if (!is_ok (error))
13543 buflen = buf.p - buf.buf;
13544 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13545 if (!is_ok (error)) goto fail;
13546 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13547 sigbuffer_free (&buf);
13551 sigbuffer_free (&buf);
13556 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13559 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13560 mono_error_set_pending_exception (&error);
13565 MonoMethod *handle;
13566 MonoDomain *domain;
13567 } DynamicMethodReleaseData;
13570 * The runtime automatically clean up those after finalization.
13572 static MonoReferenceQueue *dynamic_method_queue;
13575 free_dynamic_method (void *dynamic_method)
13577 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13578 MonoDomain *domain = data->domain;
13579 MonoMethod *method = data->handle;
13582 mono_domain_lock (domain);
13583 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13584 g_hash_table_remove (domain->method_to_dyn_method, method);
13585 mono_domain_unlock (domain);
13586 g_assert (dis_link);
13587 mono_gchandle_free (dis_link);
13589 mono_runtime_free_method (domain, method);
13594 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13596 MonoReferenceQueue *queue;
13597 MonoMethod *handle;
13598 DynamicMethodReleaseData *release_data;
13599 ReflectionMethodBuilder rmb;
13600 MonoMethodSignature *sig;
13602 MonoDomain *domain;
13606 mono_error_init (error);
13608 if (mono_runtime_is_shutting_down ()) {
13609 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13613 if (!(queue = dynamic_method_queue)) {
13614 mono_loader_lock ();
13615 if (!(queue = dynamic_method_queue))
13616 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13617 mono_loader_unlock ();
13620 sig = dynamic_method_to_signature (mb, error);
13621 return_val_if_nok (error, FALSE);
13623 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13626 * Resolve references.
13629 * Every second entry in the refs array is reserved for storing handle_class,
13630 * which is needed by the ldtoken implementation in the JIT.
13632 rmb.nrefs = mb->nrefs;
13633 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13634 for (i = 0; i < mb->nrefs; i += 2) {
13635 MonoClass *handle_class;
13637 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13639 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13640 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13642 * The referenced DynamicMethod should already be created by the managed
13643 * code, except in the case of circular references. In that case, we store
13644 * method in the refs array, and fix it up later when the referenced
13645 * DynamicMethod is created.
13647 if (method->mhandle) {
13648 ref = method->mhandle;
13650 /* FIXME: GC object stored in unmanaged memory */
13653 /* FIXME: GC object stored in unmanaged memory */
13654 method->referenced_by = g_slist_append (method->referenced_by, mb);
13656 handle_class = mono_defaults.methodhandle_class;
13658 MonoException *ex = NULL;
13659 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13660 if (!is_ok (error)) {
13665 ex = mono_get_exception_type_load (NULL, NULL);
13666 else if (mono_security_core_clr_enabled ())
13667 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13671 mono_error_set_exception_instance (error, ex);
13676 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13677 rmb.refs [i + 1] = handle_class;
13681 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13682 if (!is_ok (error)) {
13686 klass = mono_class_from_mono_type (owner_type);
13688 klass = mono_defaults.object_class;
13691 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13693 return_val_if_nok (error, FALSE);
13695 release_data = g_new (DynamicMethodReleaseData, 1);
13696 release_data->handle = handle;
13697 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13698 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13699 g_free (release_data);
13701 /* Fix up refs entries pointing at us */
13702 for (l = mb->referenced_by; l; l = l->next) {
13703 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13704 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13707 g_assert (method->mhandle);
13709 data = (gpointer*)wrapper->method_data;
13710 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13711 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13712 data [i + 1] = mb->mhandle;
13715 g_slist_free (mb->referenced_by);
13717 /* ilgen is no longer needed */
13720 domain = mono_domain_get ();
13721 mono_domain_lock (domain);
13722 if (!domain->method_to_dyn_method)
13723 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13724 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13725 mono_domain_unlock (domain);
13731 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13734 (void) reflection_create_dynamic_method (mb, &error);
13735 mono_error_set_pending_exception (&error);
13738 #endif /* DISABLE_REFLECTION_EMIT */
13742 * mono_reflection_is_valid_dynamic_token:
13744 * Returns TRUE if token is valid.
13748 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13750 return lookup_dyn_token (image, token) != NULL;
13753 MonoMethodSignature *
13754 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13756 MonoMethodSignature *sig;
13757 g_assert (image_is_dynamic (image));
13759 mono_error_init (error);
13761 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13765 return mono_method_signature_checked (method, error);
13768 #ifndef DISABLE_REFLECTION_EMIT
13771 * mono_reflection_lookup_dynamic_token:
13773 * Finish the Builder object pointed to by TOKEN and return the corresponding
13774 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13775 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13778 * LOCKING: Take the loader lock
13781 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13783 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13787 mono_error_init (error);
13789 obj = lookup_dyn_token (assembly, token);
13792 g_error ("Could not find required dynamic token 0x%08x", token);
13794 mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13800 handle_class = &klass;
13801 gpointer result = resolve_object (image, obj, handle_class, context, error);
13806 * ensure_complete_type:
13808 * Ensure that KLASS is completed if it is a dynamic type, or references
13812 ensure_complete_type (MonoClass *klass, MonoError *error)
13814 mono_error_init (error);
13816 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13817 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13819 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13820 return_if_nok (error);
13822 // Asserting here could break a lot of code
13823 //g_assert (klass->wastypebuilder);
13826 if (klass->generic_class) {
13827 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13830 for (i = 0; i < inst->type_argc; ++i) {
13831 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13832 return_if_nok (error);
13838 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13840 gpointer result = NULL;
13842 mono_error_init (error);
13844 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13845 result = mono_string_intern_checked ((MonoString*)obj, error);
13846 return_val_if_nok (error, NULL);
13847 *handle_class = mono_defaults.string_class;
13849 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13850 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13851 return_val_if_nok (error, NULL);
13852 MonoClass *mc = mono_class_from_mono_type (type);
13853 if (!mono_class_init (mc)) {
13854 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13859 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13860 return_val_if_nok (error, NULL);
13862 result = mono_class_from_mono_type (inflated);
13863 mono_metadata_free_type (inflated);
13865 result = mono_class_from_mono_type (type);
13867 *handle_class = mono_defaults.typehandle_class;
13869 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13870 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13871 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13872 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13873 result = ((MonoReflectionMethod*)obj)->method;
13875 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13876 mono_error_assert_ok (error);
13878 *handle_class = mono_defaults.methodhandle_class;
13880 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13881 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13882 result = mb->mhandle;
13884 /* Type is not yet created */
13885 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13887 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13888 return_val_if_nok (error, NULL);
13891 * Hopefully this has been filled in by calling CreateType() on the
13895 * TODO: This won't work if the application finishes another
13896 * TypeBuilder instance instead of this one.
13898 result = mb->mhandle;
13901 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13902 mono_error_assert_ok (error);
13904 *handle_class = mono_defaults.methodhandle_class;
13905 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13906 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13908 result = cb->mhandle;
13910 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13912 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13913 return_val_if_nok (error, NULL);
13914 result = cb->mhandle;
13917 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13918 mono_error_assert_ok (error);
13920 *handle_class = mono_defaults.methodhandle_class;
13921 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13922 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13924 ensure_complete_type (field->parent, error);
13925 return_val_if_nok (error, NULL);
13928 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13929 return_val_if_nok (error, NULL);
13931 MonoClass *klass = mono_class_from_mono_type (inflated);
13932 MonoClassField *inflated_field;
13933 gpointer iter = NULL;
13934 mono_metadata_free_type (inflated);
13935 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13936 if (!strcmp (field->name, inflated_field->name))
13939 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13940 result = inflated_field;
13944 *handle_class = mono_defaults.fieldhandle_class;
13946 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13947 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13948 result = fb->handle;
13951 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13953 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13954 return_val_if_nok (error, NULL);
13955 result = fb->handle;
13958 if (fb->handle && fb->handle->parent->generic_container) {
13959 MonoClass *klass = fb->handle->parent;
13960 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13961 return_val_if_nok (error, NULL);
13963 MonoClass *inflated = mono_class_from_mono_type (type);
13965 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13967 mono_metadata_free_type (type);
13969 *handle_class = mono_defaults.fieldhandle_class;
13970 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13971 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13972 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13973 return_val_if_nok (error, NULL);
13976 klass = type->data.klass;
13977 if (klass->wastypebuilder) {
13978 /* Already created */
13982 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13983 return_val_if_nok (error, NULL);
13984 result = type->data.klass;
13987 *handle_class = mono_defaults.typehandle_class;
13988 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13989 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13990 MonoMethodSignature *sig;
13993 if (helper->arguments)
13994 nargs = mono_array_length (helper->arguments);
13998 sig = mono_metadata_signature_alloc (image, nargs);
13999 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14000 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14002 if (helper->unmanaged_call_conv) { /* unmanaged */
14003 sig->call_convention = helper->unmanaged_call_conv - 1;
14004 sig->pinvoke = TRUE;
14005 } else if (helper->call_conv & 0x02) {
14006 sig->call_convention = MONO_CALL_VARARG;
14008 sig->call_convention = MONO_CALL_DEFAULT;
14011 sig->param_count = nargs;
14012 /* TODO: Copy type ? */
14013 sig->ret = helper->return_type->type;
14014 for (i = 0; i < nargs; ++i) {
14015 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14016 if (!is_ok (error)) {
14017 image_g_free (image, sig);
14023 *handle_class = NULL;
14024 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14025 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14026 /* Already created by the managed code */
14027 g_assert (method->mhandle);
14028 result = method->mhandle;
14029 *handle_class = mono_defaults.methodhandle_class;
14030 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14031 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14032 return_val_if_nok (error, NULL);
14033 type = mono_class_inflate_generic_type_checked (type, context, error);
14034 return_val_if_nok (error, NULL);
14036 result = mono_class_from_mono_type (type);
14037 *handle_class = mono_defaults.typehandle_class;
14039 mono_metadata_free_type (type);
14040 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14041 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14042 return_val_if_nok (error, NULL);
14043 type = mono_class_inflate_generic_type_checked (type, context, error);
14044 return_val_if_nok (error, NULL);
14046 result = mono_class_from_mono_type (type);
14047 *handle_class = mono_defaults.typehandle_class;
14049 mono_metadata_free_type (type);
14050 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14051 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14052 MonoClass *inflated;
14054 MonoClassField *field;
14056 if (is_sre_field_builder (mono_object_class (f->fb)))
14057 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14058 else if (is_sr_mono_field (mono_object_class (f->fb)))
14059 field = ((MonoReflectionField*)f->fb)->field;
14061 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)));
14063 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14064 return_val_if_nok (error, NULL);
14065 type = mono_class_inflate_generic_type_checked (finst, context, error);
14066 return_val_if_nok (error, NULL);
14068 inflated = mono_class_from_mono_type (type);
14070 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14071 ensure_complete_type (field->parent, error);
14072 if (!is_ok (error)) {
14073 mono_metadata_free_type (type);
14078 mono_metadata_free_type (type);
14079 *handle_class = mono_defaults.fieldhandle_class;
14080 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14081 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14082 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14083 return_val_if_nok (error, NULL);
14084 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14085 return_val_if_nok (error, NULL);
14087 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14088 MonoMethod *method;
14090 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14091 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14092 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14093 method = ((MonoReflectionMethod *)c->cb)->method;
14095 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)));
14097 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14098 *handle_class = mono_defaults.methodhandle_class;
14099 mono_metadata_free_type (type);
14100 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14101 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14102 if (m->method_args) {
14103 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14104 return_val_if_nok (error, NULL);
14106 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14107 mono_error_assert_ok (error);
14110 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14111 return_val_if_nok (error, NULL);
14112 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14113 return_val_if_nok (error, NULL);
14115 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14116 MonoMethod *method;
14118 if (is_sre_method_builder (mono_object_class (m->mb)))
14119 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14120 else if (is_sr_mono_method (mono_object_class (m->mb)))
14121 method = ((MonoReflectionMethod *)m->mb)->method;
14123 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)));
14125 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14126 mono_metadata_free_type (type);
14128 *handle_class = mono_defaults.methodhandle_class;
14129 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14130 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14133 MonoMethod *method;
14137 mtype = mono_reflection_type_get_handle (m->parent, error);
14138 return_val_if_nok (error, NULL);
14139 klass = mono_class_from_mono_type (mtype);
14141 /* Find the method */
14143 name = mono_string_to_utf8 (m->name);
14145 while ((method = mono_class_get_methods (klass, &iter))) {
14146 if (!strcmp (method->name, name))
14153 // FIXME: Check parameters/return value etc. match
14156 *handle_class = mono_defaults.methodhandle_class;
14157 } else if (is_sre_array (mono_object_get_class(obj)) ||
14158 is_sre_byref (mono_object_get_class(obj)) ||
14159 is_sre_pointer (mono_object_get_class(obj))) {
14160 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14161 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14162 return_val_if_nok (error, NULL);
14165 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14166 return_val_if_nok (error, NULL);
14168 result = mono_class_from_mono_type (inflated);
14169 mono_metadata_free_type (inflated);
14171 result = mono_class_from_mono_type (type);
14173 *handle_class = mono_defaults.typehandle_class;
14175 g_print ("%s\n", obj->vtable->klass->name);
14176 g_assert_not_reached ();
14181 #else /* DISABLE_REFLECTION_EMIT */
14184 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14186 g_assert_not_reached ();
14191 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14193 g_assert_not_reached ();
14197 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14199 g_assert_not_reached ();
14203 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14205 g_assert_not_reached ();
14210 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14212 g_assert_not_reached ();
14216 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14218 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14222 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14224 g_assert_not_reached ();
14228 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14230 g_assert_not_reached ();
14233 MonoReflectionModule *
14234 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14236 g_assert_not_reached ();
14241 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14243 g_assert_not_reached ();
14248 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14250 g_assert_not_reached ();
14255 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14256 gboolean create_open_instance, gboolean register_token, MonoError *error)
14258 g_assert_not_reached ();
14263 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14268 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14270 g_assert_not_reached ();
14274 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14276 mono_error_init (error);
14278 *num_overrides = 0;
14281 MonoReflectionEvent *
14282 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14284 g_assert_not_reached ();
14288 MonoReflectionType*
14289 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14291 g_assert_not_reached ();
14296 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14298 g_assert_not_reached ();
14302 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14304 g_assert_not_reached ();
14309 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14311 g_assert_not_reached ();
14316 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14321 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14323 mono_error_init (error);
14328 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14330 mono_error_init (error);
14337 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14339 g_assert_not_reached ();
14342 #endif /* DISABLE_REFLECTION_EMIT */
14344 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14345 const static guint32 declsec_flags_map[] = {
14346 0x00000000, /* empty */
14347 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14348 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14349 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14350 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14351 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14352 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14353 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14354 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14355 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14356 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14357 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14358 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14359 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14360 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14361 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14362 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14363 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14364 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14368 * Returns flags that includes all available security action associated to the handle.
14369 * @token: metadata token (either for a class or a method)
14370 * @image: image where resides the metadata.
14373 mono_declsec_get_flags (MonoImage *image, guint32 token)
14375 int index = mono_metadata_declsec_from_index (image, token);
14376 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14377 guint32 result = 0;
14381 /* HasSecurity can be present for other, not specially encoded, attributes,
14382 e.g. SuppressUnmanagedCodeSecurityAttribute */
14386 for (i = index; i < t->rows; i++) {
14387 guint32 cols [MONO_DECL_SECURITY_SIZE];
14389 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14390 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14393 action = cols [MONO_DECL_SECURITY_ACTION];
14394 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14395 result |= declsec_flags_map [action];
14397 g_assert_not_reached ();
14404 * Get the security actions (in the form of flags) associated with the specified method.
14406 * @method: The method for which we want the declarative security flags.
14407 * Return the declarative security flags for the method (only).
14409 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14410 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14413 mono_declsec_flags_from_method (MonoMethod *method)
14415 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14416 /* FIXME: No cache (for the moment) */
14417 guint32 idx = mono_method_get_index (method);
14418 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14419 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14420 return mono_declsec_get_flags (method->klass->image, idx);
14426 * Get the security actions (in the form of flags) associated with the specified class.
14428 * @klass: The class for which we want the declarative security flags.
14429 * Return the declarative security flags for the class.
14431 * Note: We cache the flags inside the MonoClass structure as this will get
14432 * called very often (at least for each method).
14435 mono_declsec_flags_from_class (MonoClass *klass)
14437 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14438 if (!klass->ext || !klass->ext->declsec_flags) {
14441 idx = mono_metadata_token_index (klass->type_token);
14442 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14443 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14444 mono_loader_lock ();
14445 mono_class_alloc_ext (klass);
14446 mono_loader_unlock ();
14447 /* we cache the flags on classes */
14448 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14450 return klass->ext->declsec_flags;
14456 * Get the security actions (in the form of flags) associated with the specified assembly.
14458 * @assembly: The assembly for which we want the declarative security flags.
14459 * Return the declarative security flags for the assembly.
14462 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14464 guint32 idx = 1; /* there is only one assembly */
14465 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14466 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14467 return mono_declsec_get_flags (assembly->image, idx);
14472 * Fill actions for the specific index (which may either be an encoded class token or
14473 * an encoded method token) from the metadata image.
14474 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14477 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14478 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14480 MonoBoolean result = FALSE;
14482 guint32 cols [MONO_DECL_SECURITY_SIZE];
14483 int index = mono_metadata_declsec_from_index (image, token);
14486 t = &image->tables [MONO_TABLE_DECLSECURITY];
14487 for (i = index; i < t->rows; i++) {
14488 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14490 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14493 /* if present only replace (class) permissions with method permissions */
14494 /* if empty accept either class or method permissions */
14495 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14496 if (!actions->demand.blob) {
14497 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14498 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14499 actions->demand.blob = (char*) (blob + 2);
14500 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14503 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14504 if (!actions->noncasdemand.blob) {
14505 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14506 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14507 actions->noncasdemand.blob = (char*) (blob + 2);
14508 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14511 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14512 if (!actions->demandchoice.blob) {
14513 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14514 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14515 actions->demandchoice.blob = (char*) (blob + 2);
14516 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14526 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14527 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14529 guint32 idx = mono_metadata_token_index (klass->type_token);
14530 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14531 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14532 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14536 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14537 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14539 guint32 idx = mono_method_get_index (method);
14540 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14541 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14542 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14546 * Collect all actions (that requires to generate code in mini) assigned for
14547 * the specified method.
14548 * Note: Don't use the content of actions if the function return FALSE.
14551 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14553 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14554 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14555 MonoBoolean result = FALSE;
14558 /* quick exit if no declarative security is present in the metadata */
14559 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14562 /* we want the original as the wrapper is "free" of the security informations */
14563 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14564 method = mono_marshal_method_from_wrapper (method);
14569 /* First we look for method-level attributes */
14570 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14571 mono_class_init (method->klass);
14572 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14574 result = mono_declsec_get_method_demands_params (method, demands,
14575 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14578 /* Here we use (or create) the class declarative cache to look for demands */
14579 flags = mono_declsec_flags_from_class (method->klass);
14580 if (flags & mask) {
14582 mono_class_init (method->klass);
14583 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14585 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14586 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14589 /* The boolean return value is used as a shortcut in case nothing needs to
14590 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14596 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14598 * Note: Don't use the content of actions if the function return FALSE.
14601 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14603 MonoBoolean result = FALSE;
14606 /* quick exit if no declarative security is present in the metadata */
14607 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14610 /* we want the original as the wrapper is "free" of the security informations */
14611 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14612 method = mono_marshal_method_from_wrapper (method);
14617 /* results are independant - zeroize both */
14618 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14619 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14621 /* First we look for method-level attributes */
14622 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14623 mono_class_init (method->klass);
14625 result = mono_declsec_get_method_demands_params (method, cmethod,
14626 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14629 /* Here we use (or create) the class declarative cache to look for demands */
14630 flags = mono_declsec_flags_from_class (method->klass);
14631 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14632 mono_class_init (method->klass);
14634 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14635 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14642 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14644 * @klass The inherited class - this is the class that provides the security check (attributes)
14646 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14648 * Note: Don't use the content of actions if the function return FALSE.
14651 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14653 MonoBoolean result = FALSE;
14656 /* quick exit if no declarative security is present in the metadata */
14657 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14660 /* Here we use (or create) the class declarative cache to look for demands */
14661 flags = mono_declsec_flags_from_class (klass);
14662 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14663 mono_class_init (klass);
14664 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14666 result |= mono_declsec_get_class_demands_params (klass, demands,
14667 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14674 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14676 * Note: Don't use the content of actions if the function return FALSE.
14679 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14681 /* quick exit if no declarative security is present in the metadata */
14682 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14685 /* we want the original as the wrapper is "free" of the security informations */
14686 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14687 method = mono_marshal_method_from_wrapper (method);
14692 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14693 mono_class_init (method->klass);
14694 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14696 return mono_declsec_get_method_demands_params (method, demands,
14697 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14704 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14706 guint32 cols [MONO_DECL_SECURITY_SIZE];
14710 int index = mono_metadata_declsec_from_index (image, token);
14714 t = &image->tables [MONO_TABLE_DECLSECURITY];
14715 for (i = index; i < t->rows; i++) {
14716 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14718 /* shortcut - index are ordered */
14719 if (token != cols [MONO_DECL_SECURITY_PARENT])
14722 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14723 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14724 entry->blob = (char*) (metadata + 2);
14725 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14734 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14736 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14737 guint32 idx = mono_method_get_index (method);
14738 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14739 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14740 return get_declsec_action (method->klass->image, idx, action, entry);
14746 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14749 guint32 flags = mono_declsec_flags_from_class (klass);
14750 if (declsec_flags_map [action] & flags) {
14751 guint32 idx = mono_metadata_token_index (klass->type_token);
14752 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14753 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14754 return get_declsec_action (klass->image, idx, action, entry);
14760 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14762 guint32 idx = 1; /* there is only one assembly */
14763 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14764 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14766 return get_declsec_action (assembly->image, idx, action, entry);
14770 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14772 MonoObject *res, *exc;
14774 static MonoMethod *method = NULL;
14776 mono_error_init (error);
14778 if (method == NULL) {
14779 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14784 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14785 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14787 g_assert (mono_class_get_ref_info (klass));
14788 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14790 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14791 return_val_if_nok (error, FALSE);
14793 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14795 if (exc || !mono_error_ok (error)) {
14796 mono_error_cleanup (error);
14799 return *(MonoBoolean*)mono_object_unbox (res);
14803 * mono_reflection_type_get_type:
14804 * @reftype: the System.Type object
14806 * Returns the MonoType* associated with the C# System.Type object @reftype.
14809 mono_reflection_type_get_type (MonoReflectionType *reftype)
14811 g_assert (reftype);
14814 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14815 mono_error_assert_ok (&error);
14820 * mono_reflection_assembly_get_assembly:
14821 * @refassembly: the System.Reflection.Assembly object
14823 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14826 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14828 g_assert (refassembly);
14830 return refassembly->assembly;