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
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA 0x00002000
63 MonoReflectionILGen *ilgen;
64 MonoReflectionType *rtype;
65 MonoArray *parameters;
66 MonoArray *generic_params;
67 MonoGenericContainer *generic_container;
73 guint32 *table_idx; /* note: it's a pointer */
77 MonoBoolean init_locals;
78 MonoBoolean skip_visibility;
79 MonoArray *return_modreq;
80 MonoArray *return_modopt;
81 MonoArray *param_modreq;
82 MonoArray *param_modopt;
83 MonoArray *permissions;
88 int charset, extra_flags, native_cc;
89 MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
94 MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
107 MONO_INTERFACEIMPL_SIZE,
108 MONO_MEMBERREF_SIZE, /* 0x0A */
110 MONO_CUSTOM_ATTR_SIZE,
111 MONO_FIELD_MARSHAL_SIZE,
112 MONO_DECL_SECURITY_SIZE,
113 MONO_CLASS_LAYOUT_SIZE,
114 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115 MONO_STAND_ALONE_SIGNATURE_SIZE,
119 MONO_PROPERTY_MAP_SIZE,
122 MONO_METHOD_SEMA_SIZE,
123 MONO_METHODIMPL_SIZE,
124 MONO_MODULEREF_SIZE, /* 0x1A */
130 MONO_ASSEMBLY_SIZE, /* 0x20 */
131 MONO_ASSEMBLY_PROCESSOR_SIZE,
132 MONO_ASSEMBLYOS_SIZE,
133 MONO_ASSEMBLYREF_SIZE,
134 MONO_ASSEMBLYREFPROC_SIZE,
135 MONO_ASSEMBLYREFOS_SIZE,
139 MONO_NESTED_CLASS_SIZE,
141 MONO_GENERICPARAM_SIZE, /* 0x2A */
142 MONO_METHODSPEC_SIZE,
143 MONO_GENPARCONSTRAINT_SIZE
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
198 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
199 __type = mono_reflection_type_resolve_user_types (__type); \
200 mono_array_set (arr, MonoReflectionType*, index, __type); \
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
219 mono_reflection_init (void)
224 sigbuffer_init (SigBuffer *buf, int size)
226 buf->buf = g_malloc (size);
228 buf->end = buf->buf + size;
232 sigbuffer_make_room (SigBuffer *buf, int size)
234 if (buf->end - buf->p < size) {
235 int new_size = buf->end - buf->buf + size + 32;
236 char *p = g_realloc (buf->buf, new_size);
237 size = buf->p - buf->buf;
240 buf->end = buf->buf + new_size;
245 sigbuffer_add_value (SigBuffer *buf, guint32 val)
247 sigbuffer_make_room (buf, 6);
248 mono_metadata_encode_value (val, buf->p, &buf->p);
252 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
254 sigbuffer_make_room (buf, 1);
260 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
262 sigbuffer_make_room (buf, size);
263 memcpy (buf->p, p, size);
268 sigbuffer_free (SigBuffer *buf)
273 #ifndef DISABLE_REFLECTION_EMIT
277 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281 image_g_malloc (MonoImage *image, guint size)
284 return mono_image_alloc (image, size);
286 return g_malloc (size);
288 #endif /* !DISABLE_REFLECTION_EMIT */
293 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
297 image_g_malloc0 (MonoImage *image, guint size)
300 return mono_image_alloc0 (image, size);
302 return g_malloc0 (size);
305 #ifndef DISABLE_REFLECTION_EMIT
307 image_strdup (MonoImage *image, const char *s)
310 return mono_image_strdup (image, s);
316 #define image_g_new(image,struct_type, n_structs) \
317 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
319 #define image_g_new0(image,struct_type, n_structs) \
320 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
324 alloc_table (MonoDynamicTable *table, guint nrows)
327 g_assert (table->columns);
328 if (nrows + 1 >= table->alloc_rows) {
329 while (nrows + 1 >= table->alloc_rows) {
330 if (table->alloc_rows == 0)
331 table->alloc_rows = 16;
333 table->alloc_rows *= 2;
336 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
341 make_room_in_stream (MonoDynamicStream *stream, int size)
343 if (size <= stream->alloc_size)
346 while (stream->alloc_size <= size) {
347 if (stream->alloc_size < 4096)
348 stream->alloc_size = 4096;
350 stream->alloc_size *= 2;
353 stream->data = g_realloc (stream->data, stream->alloc_size);
357 string_heap_insert (MonoDynamicStream *sh, const char *str)
361 gpointer oldkey, oldval;
363 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
364 return GPOINTER_TO_UINT (oldval);
366 len = strlen (str) + 1;
369 make_room_in_stream (sh, idx + len);
372 * We strdup the string even if we already copy them in sh->data
373 * so that the string pointers in the hash remain valid even if
374 * we need to realloc sh->data. We may want to avoid that later.
376 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
377 memcpy (sh->data + idx, str, len);
383 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
385 char *name = mono_string_to_utf8 (str);
387 idx = string_heap_insert (sh, name);
392 #ifndef DISABLE_REFLECTION_EMIT
394 string_heap_init (MonoDynamicStream *sh)
397 sh->alloc_size = 4096;
398 sh->data = g_malloc (4096);
399 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
400 string_heap_insert (sh, "");
405 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
409 make_room_in_stream (stream, stream->index + len);
410 memcpy (stream->data + stream->index, data, len);
412 stream->index += len;
414 * align index? Not without adding an additional param that controls it since
415 * we may store a blob value in pieces.
421 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
425 make_room_in_stream (stream, stream->index + len);
426 memset (stream->data + stream->index, 0, len);
428 stream->index += len;
433 stream_data_align (MonoDynamicStream *stream)
436 guint32 count = stream->index % 4;
438 /* we assume the stream data will be aligned */
440 mono_image_add_stream_data (stream, buf, 4 - count);
443 #ifndef DISABLE_REFLECTION_EMIT
445 mono_blob_entry_hash (const char* str)
449 len = mono_metadata_decode_blob_size (str, &str);
453 for (str += 1; str < end; str++)
454 h = (h << 5) - h + *str;
462 mono_blob_entry_equal (const char *str1, const char *str2) {
466 len = mono_metadata_decode_blob_size (str1, &end1);
467 len2 = mono_metadata_decode_blob_size (str2, &end2);
470 return memcmp (end1, end2, len) == 0;
474 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
478 gpointer oldkey, oldval;
480 copy = g_malloc (s1+s2);
481 memcpy (copy, b1, s1);
482 memcpy (copy + s1, b2, s2);
483 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
485 idx = GPOINTER_TO_UINT (oldval);
487 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
488 mono_image_add_stream_data (&assembly->blob, b2, s2);
489 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
495 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
499 guint32 size = buf->p - buf->buf;
501 g_assert (size <= (buf->end - buf->buf));
502 mono_metadata_encode_value (size, b, &b);
503 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
507 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
508 * dest may be misaligned.
511 swap_with_size (char *dest, const char* val, int len, int nelem) {
512 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
515 for (elem = 0; elem < nelem; ++elem) {
541 g_assert_not_reached ();
547 memcpy (dest, val, len * nelem);
552 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
556 guint32 idx = 0, len;
558 len = str->length * 2;
559 mono_metadata_encode_value (len, b, &b);
560 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
562 char *swapped = g_malloc (2 * mono_string_length (str));
563 const char *p = (const char*)mono_string_chars (str);
565 swap_with_size (swapped, p, 2, mono_string_length (str));
566 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
570 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
575 #ifndef DISABLE_REFLECTION_EMIT
577 default_class_from_mono_type (MonoType *type)
579 switch (type->type) {
580 case MONO_TYPE_OBJECT:
581 return mono_defaults.object_class;
583 return mono_defaults.void_class;
584 case MONO_TYPE_BOOLEAN:
585 return mono_defaults.boolean_class;
587 return mono_defaults.char_class;
589 return mono_defaults.sbyte_class;
591 return mono_defaults.byte_class;
593 return mono_defaults.int16_class;
595 return mono_defaults.uint16_class;
597 return mono_defaults.int32_class;
599 return mono_defaults.uint32_class;
601 return mono_defaults.int_class;
603 return mono_defaults.uint_class;
605 return mono_defaults.int64_class;
607 return mono_defaults.uint64_class;
609 return mono_defaults.single_class;
611 return mono_defaults.double_class;
612 case MONO_TYPE_STRING:
613 return mono_defaults.string_class;
615 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
616 g_assert_not_reached ();
624 * mono_class_get_ref_info:
626 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
629 mono_class_get_ref_info (MonoClass *klass)
631 if (klass->ref_info_handle == 0)
634 return mono_gchandle_get_target (klass->ref_info_handle);
638 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
640 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
641 g_assert (klass->ref_info_handle != 0);
645 mono_class_free_ref_info (MonoClass *klass)
647 if (klass->ref_info_handle) {
648 mono_gchandle_free (klass->ref_info_handle);
649 klass->ref_info_handle = 0;
654 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
657 MonoGenericInst *class_inst;
662 class_inst = gclass->context.class_inst;
664 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
665 klass = gclass->container_class;
666 sigbuffer_add_value (buf, klass->byval_arg.type);
667 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
669 sigbuffer_add_value (buf, class_inst->type_argc);
670 for (i = 0; i < class_inst->type_argc; ++i)
671 encode_type (assembly, class_inst->type_argv [i], buf);
676 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
679 g_assert_not_reached ();
684 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
688 case MONO_TYPE_BOOLEAN:
702 case MONO_TYPE_STRING:
703 case MONO_TYPE_OBJECT:
704 case MONO_TYPE_TYPEDBYREF:
705 sigbuffer_add_value (buf, type->type);
708 sigbuffer_add_value (buf, type->type);
709 encode_type (assembly, type->data.type, buf);
711 case MONO_TYPE_SZARRAY:
712 sigbuffer_add_value (buf, type->type);
713 encode_type (assembly, &type->data.klass->byval_arg, buf);
715 case MONO_TYPE_VALUETYPE:
716 case MONO_TYPE_CLASS: {
717 MonoClass *k = mono_class_from_mono_type (type);
719 if (k->generic_container) {
720 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
721 encode_generic_class (assembly, gclass, buf);
724 * Make sure we use the correct type.
726 sigbuffer_add_value (buf, k->byval_arg.type);
728 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
729 * otherwise two typerefs could point to the same type, leading to
730 * verification errors.
732 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
736 case MONO_TYPE_ARRAY:
737 sigbuffer_add_value (buf, type->type);
738 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
739 sigbuffer_add_value (buf, type->data.array->rank);
740 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
741 sigbuffer_add_value (buf, 0);
743 case MONO_TYPE_GENERICINST:
744 encode_generic_class (assembly, type->data.generic_class, buf);
748 sigbuffer_add_value (buf, type->type);
749 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
752 g_error ("need to encode type %x", type->type);
757 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
760 sigbuffer_add_value (buf, MONO_TYPE_VOID);
764 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
768 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
773 for (i = 0; i < mono_array_length (modreq); ++i) {
774 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
775 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
776 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
780 for (i = 0; i < mono_array_length (modopt); ++i) {
781 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
782 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
783 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
788 #ifndef DISABLE_REFLECTION_EMIT
790 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
794 guint32 nparams = sig->param_count;
800 sigbuffer_init (&buf, 32);
802 * FIXME: vararg, explicit_this, differenc call_conv values...
804 idx = sig->call_convention;
806 idx |= 0x20; /* hasthis */
807 if (sig->generic_param_count)
808 idx |= 0x10; /* generic */
809 sigbuffer_add_byte (&buf, idx);
810 if (sig->generic_param_count)
811 sigbuffer_add_value (&buf, sig->generic_param_count);
812 sigbuffer_add_value (&buf, nparams);
813 encode_type (assembly, sig->ret, &buf);
814 for (i = 0; i < nparams; ++i) {
815 if (i == sig->sentinelpos)
816 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817 encode_type (assembly, sig->params [i], &buf);
819 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
820 sigbuffer_free (&buf);
826 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
829 * FIXME: reuse code from method_encode_signature().
833 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
834 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
835 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
838 sigbuffer_init (&buf, 32);
839 /* LAMESPEC: all the call conv spec is foobared */
840 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
841 if (mb->call_conv & 2)
842 idx |= 0x5; /* vararg */
843 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
844 idx |= 0x20; /* hasthis */
846 idx |= 0x10; /* generic */
847 sigbuffer_add_byte (&buf, idx);
849 sigbuffer_add_value (&buf, ngparams);
850 sigbuffer_add_value (&buf, nparams + notypes);
851 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
852 encode_reflection_type (assembly, mb->rtype, &buf);
853 for (i = 0; i < nparams; ++i) {
854 MonoArray *modreq = NULL;
855 MonoArray *modopt = NULL;
856 MonoReflectionType *pt;
858 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
859 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
860 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
861 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
862 encode_custom_modifiers (assembly, modreq, modopt, &buf);
863 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
864 encode_reflection_type (assembly, pt, &buf);
867 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
868 for (i = 0; i < notypes; ++i) {
869 MonoReflectionType *pt;
871 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
872 encode_reflection_type (assembly, pt, &buf);
875 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
876 sigbuffer_free (&buf);
881 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
883 MonoDynamicTable *table;
885 guint32 idx, sig_idx;
886 guint nl = mono_array_length (ilgen->locals);
890 sigbuffer_init (&buf, 32);
891 sigbuffer_add_value (&buf, 0x07);
892 sigbuffer_add_value (&buf, nl);
893 for (i = 0; i < nl; ++i) {
894 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
897 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
899 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
901 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
902 sigbuffer_free (&buf);
904 if (assembly->standalonesig_cache == NULL)
905 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
906 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
910 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
911 idx = table->next_idx ++;
913 alloc_table (table, table->rows);
914 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
916 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
918 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
924 method_count_clauses (MonoReflectionILGen *ilgen)
926 guint32 num_clauses = 0;
929 MonoILExceptionInfo *ex_info;
930 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
931 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
932 if (ex_info->handlers)
933 num_clauses += mono_array_length (ex_info->handlers);
941 #ifndef DISABLE_REFLECTION_EMIT
942 static MonoExceptionClause*
943 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
945 MonoExceptionClause *clauses;
946 MonoExceptionClause *clause;
947 MonoILExceptionInfo *ex_info;
948 MonoILExceptionBlock *ex_block;
949 guint32 finally_start;
950 int i, j, clause_index;;
952 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
955 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
956 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
957 finally_start = ex_info->start + ex_info->len;
958 if (!ex_info->handlers)
960 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962 clause = &(clauses [clause_index]);
964 clause->flags = ex_block->type;
965 clause->try_offset = ex_info->start;
967 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
968 clause->try_len = finally_start - ex_info->start;
970 clause->try_len = ex_info->len;
971 clause->handler_offset = ex_block->start;
972 clause->handler_len = ex_block->len;
973 if (ex_block->extype) {
974 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
976 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
977 clause->data.filter_offset = ex_block->filter_offset;
979 clause->data.filter_offset = 0;
981 finally_start = ex_block->start + ex_block->len;
989 #endif /* !DISABLE_REFLECTION_EMIT */
992 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
998 gint32 num_locals = 0;
999 gint32 num_exception = 0;
1002 char fat_header [12];
1004 guint16 short_value;
1005 guint32 local_sig = 0;
1006 guint32 header_size = 12;
1009 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1010 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1014 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1016 code = mb->ilgen->code;
1017 code_size = mb->ilgen->code_len;
1018 max_stack = mb->ilgen->max_stack;
1019 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1020 if (mb->ilgen->ex_handlers)
1021 num_exception = method_count_clauses (mb->ilgen);
1025 char *name = mono_string_to_utf8 (mb->name);
1026 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1027 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1030 mono_raise_exception (exception);
1033 code_size = mono_array_length (code);
1034 max_stack = 8; /* we probably need to run a verifier on the code... */
1037 stream_data_align (&assembly->code);
1039 /* check for exceptions, maxstack, locals */
1040 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1042 if (code_size < 64 && !(code_size & 1)) {
1043 flags = (code_size << 2) | 0x2;
1044 } else if (code_size < 32 && (code_size & 1)) {
1045 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1049 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1050 /* add to the fixup todo list */
1051 if (mb->ilgen && mb->ilgen->num_token_fixups)
1052 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1053 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1054 return assembly->text_rva + idx;
1058 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1060 * FIXME: need to set also the header size in fat_flags.
1061 * (and more sects and init locals flags)
1065 fat_flags |= METHOD_HEADER_MORE_SECTS;
1066 if (mb->init_locals)
1067 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1068 fat_header [0] = fat_flags;
1069 fat_header [1] = (header_size / 4 ) << 4;
1070 short_value = GUINT16_TO_LE (max_stack);
1071 memcpy (fat_header + 2, &short_value, 2);
1072 int_value = GUINT32_TO_LE (code_size);
1073 memcpy (fat_header + 4, &int_value, 4);
1074 int_value = GUINT32_TO_LE (local_sig);
1075 memcpy (fat_header + 8, &int_value, 4);
1076 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1077 /* add to the fixup todo list */
1078 if (mb->ilgen && mb->ilgen->num_token_fixups)
1079 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1081 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1082 if (num_exception) {
1083 unsigned char sheader [4];
1084 MonoILExceptionInfo * ex_info;
1085 MonoILExceptionBlock * ex_block;
1088 stream_data_align (&assembly->code);
1089 /* always use fat format for now */
1090 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1091 num_exception *= 6 * sizeof (guint32);
1092 num_exception += 4; /* include the size of the header */
1093 sheader [1] = num_exception & 0xff;
1094 sheader [2] = (num_exception >> 8) & 0xff;
1095 sheader [3] = (num_exception >> 16) & 0xff;
1096 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1097 /* fat header, so we are already aligned */
1099 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1100 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1101 if (ex_info->handlers) {
1102 int finally_start = ex_info->start + ex_info->len;
1103 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1105 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1107 val = GUINT32_TO_LE (ex_block->type);
1108 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1110 val = GUINT32_TO_LE (ex_info->start);
1111 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1112 /* need fault, too, probably */
1113 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1114 val = GUINT32_TO_LE (finally_start - ex_info->start);
1116 val = GUINT32_TO_LE (ex_info->len);
1117 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118 /* handler offset */
1119 val = GUINT32_TO_LE (ex_block->start);
1120 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122 val = GUINT32_TO_LE (ex_block->len);
1123 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1124 finally_start = ex_block->start + ex_block->len;
1125 if (ex_block->extype) {
1126 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1128 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129 val = ex_block->filter_offset;
1133 val = GUINT32_TO_LE (val);
1134 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1135 /*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",
1136 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);*/
1139 g_error ("No clauses for ex info block %d", i);
1143 return assembly->text_rva + idx;
1147 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1150 MonoDynamicTable *table;
1153 table = &assembly->tables [table_idx];
1155 g_assert (col < table->columns);
1157 values = table->values + table->columns;
1158 for (i = 1; i <= table->rows; ++i) {
1159 if (values [col] == token)
1161 values += table->columns;
1167 * LOCKING: Acquires the loader lock.
1169 static MonoCustomAttrInfo*
1170 lookup_custom_attr (MonoImage *image, gpointer member)
1172 MonoCustomAttrInfo* res;
1174 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1179 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1185 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1187 /* FIXME: Need to do more checks */
1188 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1189 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1191 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1198 static MonoCustomAttrInfo*
1199 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1201 int i, index, count, not_visible;
1202 MonoCustomAttrInfo *ainfo;
1203 MonoReflectionCustomAttr *cattr;
1207 /* FIXME: check in assembly the Run flag is set */
1209 count = mono_array_length (cattrs);
1211 /* Skip nonpublic attributes since MS.NET seems to do the same */
1212 /* FIXME: This needs to be done more globally */
1214 for (i = 0; i < count; ++i) {
1215 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216 if (!custom_attr_visible (image, cattr))
1219 count -= not_visible;
1221 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1223 ainfo->image = image;
1224 ainfo->num_attrs = count;
1225 ainfo->cached = alloc_img != NULL;
1227 for (i = 0; i < count; ++i) {
1228 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1229 if (custom_attr_visible (image, cattr)) {
1230 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1231 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1232 ainfo->attrs [index].ctor = cattr->ctor->method;
1233 ainfo->attrs [index].data = saved;
1234 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1242 #ifndef DISABLE_REFLECTION_EMIT
1244 * LOCKING: Acquires the loader lock.
1247 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1249 MonoCustomAttrInfo *ainfo, *tmp;
1251 if (!cattrs || !mono_array_length (cattrs))
1254 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1256 mono_loader_lock ();
1257 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1259 mono_custom_attrs_free (tmp);
1260 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1261 mono_loader_unlock ();
1267 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1274 * idx is the table index of the object
1275 * type is one of MONO_CUSTOM_ATTR_*
1278 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1280 MonoDynamicTable *table;
1281 MonoReflectionCustomAttr *cattr;
1283 guint32 count, i, token;
1285 char *p = blob_size;
1287 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1290 count = mono_array_length (cattrs);
1291 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1292 table->rows += count;
1293 alloc_table (table, table->rows);
1294 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1295 idx <<= MONO_CUSTOM_ATTR_BITS;
1297 for (i = 0; i < count; ++i) {
1298 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1299 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1300 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1301 type = mono_metadata_token_index (token);
1302 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1303 switch (mono_metadata_token_table (token)) {
1304 case MONO_TABLE_METHOD:
1305 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1307 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1308 * method, not the one returned by mono_image_create_token ().
1310 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1312 case MONO_TABLE_MEMBERREF:
1313 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1316 g_warning ("got wrong token in custom attr");
1319 values [MONO_CUSTOM_ATTR_TYPE] = type;
1321 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1322 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1323 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1324 values += MONO_CUSTOM_ATTR_SIZE;
1330 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1332 MonoDynamicTable *table;
1334 guint32 count, i, idx;
1335 MonoReflectionPermissionSet *perm;
1340 count = mono_array_length (permissions);
1341 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1342 table->rows += count;
1343 alloc_table (table, table->rows);
1345 for (i = 0; i < mono_array_length (permissions); ++i) {
1346 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1348 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1350 idx = mono_metadata_token_index (parent_token);
1351 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1352 switch (mono_metadata_token_table (parent_token)) {
1353 case MONO_TABLE_TYPEDEF:
1354 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1356 case MONO_TABLE_METHOD:
1357 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1359 case MONO_TABLE_ASSEMBLY:
1360 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1363 g_assert_not_reached ();
1366 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1367 values [MONO_DECL_SECURITY_PARENT] = idx;
1368 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1375 * Fill in the MethodDef and ParamDef tables for a method.
1376 * This is used for both normal methods and constructors.
1379 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1381 MonoDynamicTable *table;
1385 /* room in this table is already allocated */
1386 table = &assembly->tables [MONO_TABLE_METHOD];
1387 *mb->table_idx = table->next_idx ++;
1388 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1389 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1390 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1391 values [MONO_METHOD_FLAGS] = mb->attrs;
1392 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1393 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1394 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1396 table = &assembly->tables [MONO_TABLE_PARAM];
1397 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1399 mono_image_add_decl_security (assembly,
1400 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1403 MonoDynamicTable *mtable;
1406 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1407 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1410 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1411 if (mono_array_get (mb->pinfo, gpointer, i))
1414 table->rows += count;
1415 alloc_table (table, table->rows);
1416 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1417 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1418 MonoReflectionParamBuilder *pb;
1419 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1420 values [MONO_PARAM_FLAGS] = pb->attrs;
1421 values [MONO_PARAM_SEQUENCE] = i;
1422 if (pb->name != NULL) {
1423 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1425 values [MONO_PARAM_NAME] = 0;
1427 values += MONO_PARAM_SIZE;
1428 if (pb->marshal_info) {
1430 alloc_table (mtable, mtable->rows);
1431 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1432 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1433 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1435 pb->table_idx = table->next_idx++;
1436 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1437 guint32 field_type = 0;
1438 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1440 alloc_table (mtable, mtable->rows);
1441 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1442 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1443 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1444 mvalues [MONO_CONSTANT_TYPE] = field_type;
1445 mvalues [MONO_CONSTANT_PADDING] = 0;
1452 #ifndef DISABLE_REFLECTION_EMIT
1454 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1456 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1458 rmb->ilgen = mb->ilgen;
1459 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1460 rmb->parameters = mb->parameters;
1461 rmb->generic_params = mb->generic_params;
1462 rmb->generic_container = mb->generic_container;
1463 rmb->opt_types = NULL;
1464 rmb->pinfo = mb->pinfo;
1465 rmb->attrs = mb->attrs;
1466 rmb->iattrs = mb->iattrs;
1467 rmb->call_conv = mb->call_conv;
1468 rmb->code = mb->code;
1469 rmb->type = mb->type;
1470 rmb->name = mb->name;
1471 rmb->table_idx = &mb->table_idx;
1472 rmb->init_locals = mb->init_locals;
1473 rmb->skip_visibility = FALSE;
1474 rmb->return_modreq = mb->return_modreq;
1475 rmb->return_modopt = mb->return_modopt;
1476 rmb->param_modreq = mb->param_modreq;
1477 rmb->param_modopt = mb->param_modopt;
1478 rmb->permissions = mb->permissions;
1479 rmb->mhandle = mb->mhandle;
1484 rmb->charset = mb->charset;
1485 rmb->extra_flags = mb->extra_flags;
1486 rmb->native_cc = mb->native_cc;
1487 rmb->dllentry = mb->dllentry;
1493 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1495 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1497 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1499 rmb->ilgen = mb->ilgen;
1500 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1501 rmb->parameters = mb->parameters;
1502 rmb->generic_params = NULL;
1503 rmb->generic_container = NULL;
1504 rmb->opt_types = NULL;
1505 rmb->pinfo = mb->pinfo;
1506 rmb->attrs = mb->attrs;
1507 rmb->iattrs = mb->iattrs;
1508 rmb->call_conv = mb->call_conv;
1510 rmb->type = mb->type;
1511 rmb->name = mono_string_new (mono_domain_get (), name);
1512 rmb->table_idx = &mb->table_idx;
1513 rmb->init_locals = mb->init_locals;
1514 rmb->skip_visibility = FALSE;
1515 rmb->return_modreq = NULL;
1516 rmb->return_modopt = NULL;
1517 rmb->param_modreq = mb->param_modreq;
1518 rmb->param_modopt = mb->param_modopt;
1519 rmb->permissions = mb->permissions;
1520 rmb->mhandle = mb->mhandle;
1526 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1528 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1530 rmb->ilgen = mb->ilgen;
1531 rmb->rtype = mb->rtype;
1532 rmb->parameters = mb->parameters;
1533 rmb->generic_params = NULL;
1534 rmb->generic_container = NULL;
1535 rmb->opt_types = NULL;
1537 rmb->attrs = mb->attrs;
1539 rmb->call_conv = mb->call_conv;
1541 rmb->type = (MonoObject *) mb->owner;
1542 rmb->name = mb->name;
1543 rmb->table_idx = NULL;
1544 rmb->init_locals = mb->init_locals;
1545 rmb->skip_visibility = mb->skip_visibility;
1546 rmb->return_modreq = NULL;
1547 rmb->return_modopt = NULL;
1548 rmb->param_modreq = NULL;
1549 rmb->param_modopt = NULL;
1550 rmb->permissions = NULL;
1551 rmb->mhandle = mb->mhandle;
1558 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1560 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1561 MonoDynamicTable *table;
1564 MonoReflectionMethod *m;
1567 if (!mb->override_methods)
1570 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1571 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1573 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1575 alloc_table (table, table->rows);
1576 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1577 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1578 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1580 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1581 switch (mono_metadata_token_table (tok)) {
1582 case MONO_TABLE_MEMBERREF:
1583 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1585 case MONO_TABLE_METHOD:
1586 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1589 g_assert_not_reached ();
1591 values [MONO_METHODIMPL_DECLARATION] = tok;
1595 #ifndef DISABLE_REFLECTION_EMIT
1597 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1599 MonoDynamicTable *table;
1601 ReflectionMethodBuilder rmb;
1604 reflection_methodbuilder_from_method_builder (&rmb, mb);
1606 mono_image_basic_method (&rmb, assembly);
1607 mb->table_idx = *rmb.table_idx;
1609 if (mb->dll) { /* It's a P/Invoke method */
1611 /* map CharSet values to on-disk values */
1612 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1613 int extra_flags = mb->extra_flags;
1614 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1616 alloc_table (table, table->rows);
1617 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1619 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1620 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1622 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1624 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1625 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1626 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1627 table = &assembly->tables [MONO_TABLE_MODULEREF];
1629 alloc_table (table, table->rows);
1630 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1631 values [MONO_IMPLMAP_SCOPE] = table->rows;
1635 if (mb->generic_params) {
1636 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1637 table->rows += mono_array_length (mb->generic_params);
1638 alloc_table (table, table->rows);
1639 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1640 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1642 mono_image_get_generic_param_info (
1643 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1650 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1652 ReflectionMethodBuilder rmb;
1654 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1656 mono_image_basic_method (&rmb, assembly);
1657 mb->table_idx = *rmb.table_idx;
1662 type_get_fully_qualified_name (MonoType *type)
1664 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1668 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1672 klass = mono_class_from_mono_type (type);
1674 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1675 ta = klass->image->assembly;
1676 if (assembly_is_dynamic (ta) || (ta == ass)) {
1677 if (klass->generic_class || klass->generic_container)
1678 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1679 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1681 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1684 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1687 #ifndef DISABLE_REFLECTION_EMIT
1688 /*field_image is the image to which the eventual custom mods have been encoded against*/
1690 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1693 guint32 idx, i, token;
1695 if (!assembly->save)
1698 sigbuffer_init (&buf, 32);
1700 sigbuffer_add_value (&buf, 0x06);
1701 /* encode custom attributes before the type */
1702 if (type->num_mods) {
1703 for (i = 0; i < type->num_mods; ++i) {
1706 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1707 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1709 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1711 token = type->modifiers [i].token;
1714 if (type->modifiers [i].required)
1715 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1717 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1719 sigbuffer_add_value (&buf, token);
1722 encode_type (assembly, type, &buf);
1723 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724 sigbuffer_free (&buf);
1730 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1734 guint32 typespec = 0;
1738 init_type_builder_generics (fb->type);
1740 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1741 class = mono_class_from_mono_type (type);
1743 sigbuffer_init (&buf, 32);
1745 sigbuffer_add_value (&buf, 0x06);
1746 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1747 /* encode custom attributes before the type */
1749 if (class->generic_container)
1750 typespec = create_typespec (assembly, type);
1753 MonoGenericClass *gclass;
1754 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1755 encode_generic_class (assembly, gclass, &buf);
1757 encode_type (assembly, type, &buf);
1759 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1760 sigbuffer_free (&buf);
1765 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1766 char blob_size [64];
1767 char *b = blob_size;
1770 guint32 idx = 0, len = 0, dummy = 0;
1772 p = buf = g_malloc (64);
1774 *ret_type = MONO_TYPE_CLASS;
1776 box_val = (char*)&dummy;
1778 box_val = ((char*)val) + sizeof (MonoObject);
1779 *ret_type = val->vtable->klass->byval_arg.type;
1782 switch (*ret_type) {
1783 case MONO_TYPE_BOOLEAN:
1788 case MONO_TYPE_CHAR:
1805 case MONO_TYPE_VALUETYPE: {
1806 MonoClass *klass = val->vtable->klass;
1808 if (klass->enumtype) {
1809 *ret_type = mono_class_enum_basetype (klass)->type;
1811 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1814 g_error ("we can't encode valuetypes, we should have never reached this line");
1817 case MONO_TYPE_CLASS:
1819 case MONO_TYPE_STRING: {
1820 MonoString *str = (MonoString*)val;
1821 /* there is no signature */
1822 len = str->length * 2;
1823 mono_metadata_encode_value (len, b, &b);
1824 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1826 char *swapped = g_malloc (2 * mono_string_length (str));
1827 const char *p = (const char*)mono_string_chars (str);
1829 swap_with_size (swapped, p, 2, mono_string_length (str));
1830 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1834 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1840 case MONO_TYPE_GENERICINST:
1841 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1844 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1847 /* there is no signature */
1848 mono_metadata_encode_value (len, b, &b);
1849 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1850 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1851 swap_with_size (blob_size, box_val, len, 1);
1852 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1854 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1862 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1867 sigbuffer_init (&buf, 32);
1869 sigbuffer_add_value (&buf, minfo->type);
1871 switch (minfo->type) {
1872 case MONO_NATIVE_BYVALTSTR:
1873 case MONO_NATIVE_BYVALARRAY:
1874 sigbuffer_add_value (&buf, minfo->count);
1876 case MONO_NATIVE_LPARRAY:
1877 if (minfo->eltype || minfo->has_size) {
1878 sigbuffer_add_value (&buf, minfo->eltype);
1879 if (minfo->has_size) {
1880 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1881 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1883 /* LAMESPEC: ElemMult is undocumented */
1884 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1888 case MONO_NATIVE_SAFEARRAY:
1890 sigbuffer_add_value (&buf, minfo->eltype);
1892 case MONO_NATIVE_CUSTOM:
1894 str = mono_string_to_utf8 (minfo->guid);
1896 sigbuffer_add_value (&buf, len);
1897 sigbuffer_add_mem (&buf, str, len);
1900 sigbuffer_add_value (&buf, 0);
1902 /* native type name */
1903 sigbuffer_add_value (&buf, 0);
1904 /* custom marshaler type name */
1905 if (minfo->marshaltype || minfo->marshaltyperef) {
1906 if (minfo->marshaltyperef)
1907 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1909 str = mono_string_to_utf8 (minfo->marshaltype);
1911 sigbuffer_add_value (&buf, len);
1912 sigbuffer_add_mem (&buf, str, len);
1915 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1916 sigbuffer_add_value (&buf, 0);
1918 if (minfo->mcookie) {
1919 str = mono_string_to_utf8 (minfo->mcookie);
1921 sigbuffer_add_value (&buf, len);
1922 sigbuffer_add_mem (&buf, str, len);
1925 sigbuffer_add_value (&buf, 0);
1931 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1932 sigbuffer_free (&buf);
1937 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1939 MonoDynamicTable *table;
1942 /* maybe this fixup should be done in the C# code */
1943 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1944 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1945 table = &assembly->tables [MONO_TABLE_FIELD];
1946 fb->table_idx = table->next_idx ++;
1947 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1948 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1949 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1950 values [MONO_FIELD_FLAGS] = fb->attrs;
1951 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1953 if (fb->offset != -1) {
1954 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1956 alloc_table (table, table->rows);
1957 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1958 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1959 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1961 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1962 guint32 field_type = 0;
1963 table = &assembly->tables [MONO_TABLE_CONSTANT];
1965 alloc_table (table, table->rows);
1966 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1967 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1968 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1969 values [MONO_CONSTANT_TYPE] = field_type;
1970 values [MONO_CONSTANT_PADDING] = 0;
1972 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1974 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1976 alloc_table (table, table->rows);
1977 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1978 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1980 * We store it in the code section because it's simpler for now.
1983 if (mono_array_length (fb->rva_data) >= 10)
1984 stream_data_align (&assembly->code);
1985 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1987 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1988 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1990 if (fb->marshal_info) {
1991 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1993 alloc_table (table, table->rows);
1994 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1995 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1996 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2001 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2004 guint32 nparams = 0;
2005 MonoReflectionMethodBuilder *mb = fb->get_method;
2006 MonoReflectionMethodBuilder *smb = fb->set_method;
2009 if (mb && mb->parameters)
2010 nparams = mono_array_length (mb->parameters);
2011 if (!mb && smb && smb->parameters)
2012 nparams = mono_array_length (smb->parameters) - 1;
2013 sigbuffer_init (&buf, 32);
2014 if (fb->call_conv & 0x20)
2015 sigbuffer_add_byte (&buf, 0x28);
2017 sigbuffer_add_byte (&buf, 0x08);
2018 sigbuffer_add_value (&buf, nparams);
2020 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2021 for (i = 0; i < nparams; ++i) {
2022 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2023 encode_reflection_type (assembly, pt, &buf);
2025 } else if (smb && smb->parameters) {
2026 /* the property type is the last param */
2027 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2028 for (i = 0; i < nparams; ++i) {
2029 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2030 encode_reflection_type (assembly, pt, &buf);
2033 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2036 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2037 sigbuffer_free (&buf);
2042 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2044 MonoDynamicTable *table;
2046 guint num_methods = 0;
2050 * we need to set things in the following tables:
2051 * PROPERTYMAP (info already filled in _get_type_info ())
2052 * PROPERTY (rows already preallocated in _get_type_info ())
2053 * METHOD (method info already done with the generic method code)
2057 table = &assembly->tables [MONO_TABLE_PROPERTY];
2058 pb->table_idx = table->next_idx ++;
2059 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2060 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2061 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2062 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2064 /* FIXME: we still don't handle 'other' methods */
2065 if (pb->get_method) num_methods ++;
2066 if (pb->set_method) num_methods ++;
2068 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2069 table->rows += num_methods;
2070 alloc_table (table, table->rows);
2072 if (pb->get_method) {
2073 semaidx = table->next_idx ++;
2074 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2075 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2076 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2077 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2079 if (pb->set_method) {
2080 semaidx = table->next_idx ++;
2081 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2082 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2083 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2084 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2086 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2087 guint32 field_type = 0;
2088 table = &assembly->tables [MONO_TABLE_CONSTANT];
2090 alloc_table (table, table->rows);
2091 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2092 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2093 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2094 values [MONO_CONSTANT_TYPE] = field_type;
2095 values [MONO_CONSTANT_PADDING] = 0;
2100 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2102 MonoDynamicTable *table;
2104 guint num_methods = 0;
2108 * we need to set things in the following tables:
2109 * EVENTMAP (info already filled in _get_type_info ())
2110 * EVENT (rows already preallocated in _get_type_info ())
2111 * METHOD (method info already done with the generic method code)
2114 table = &assembly->tables [MONO_TABLE_EVENT];
2115 eb->table_idx = table->next_idx ++;
2116 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2117 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2118 values [MONO_EVENT_FLAGS] = eb->attrs;
2119 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2122 * FIXME: we still don't handle 'other' methods
2124 if (eb->add_method) num_methods ++;
2125 if (eb->remove_method) num_methods ++;
2126 if (eb->raise_method) num_methods ++;
2128 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2129 table->rows += num_methods;
2130 alloc_table (table, table->rows);
2132 if (eb->add_method) {
2133 semaidx = table->next_idx ++;
2134 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2135 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2136 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2137 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2139 if (eb->remove_method) {
2140 semaidx = table->next_idx ++;
2141 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2142 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2143 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2144 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2146 if (eb->raise_method) {
2147 semaidx = table->next_idx ++;
2148 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2149 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2150 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2151 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2156 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2158 MonoDynamicTable *table;
2159 guint32 num_constraints, i;
2163 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2164 num_constraints = gparam->iface_constraints ?
2165 mono_array_length (gparam->iface_constraints) : 0;
2166 table->rows += num_constraints;
2167 if (gparam->base_type)
2169 alloc_table (table, table->rows);
2171 if (gparam->base_type) {
2172 table_idx = table->next_idx ++;
2173 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2175 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2176 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2177 assembly, mono_reflection_type_get_handle (gparam->base_type));
2180 for (i = 0; i < num_constraints; i++) {
2181 MonoReflectionType *constraint = mono_array_get (
2182 gparam->iface_constraints, gpointer, i);
2184 table_idx = table->next_idx ++;
2185 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2187 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2188 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2189 assembly, mono_reflection_type_get_handle (constraint));
2194 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2196 GenericParamTableEntry *entry;
2199 * The GenericParam table must be sorted according to the `owner' field.
2200 * We need to do this sorting prior to writing the GenericParamConstraint
2201 * table, since we have to use the final GenericParam table indices there
2202 * and they must also be sorted.
2205 entry = g_new0 (GenericParamTableEntry, 1);
2206 entry->owner = owner;
2207 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2208 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2209 entry->gparam = gparam;
2211 g_ptr_array_add (assembly->gen_params, entry);
2215 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2217 MonoDynamicTable *table;
2218 MonoGenericParam *param;
2222 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2223 table_idx = table->next_idx ++;
2224 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2226 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2228 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2229 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2230 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2231 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2233 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2235 encode_constraints (entry->gparam, table_idx, assembly);
2239 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2241 MonoDynamicTable *table;
2244 guint32 cols [MONO_ASSEMBLY_SIZE];
2248 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2251 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2252 table = &assembly->tables [MONO_TABLE_MODULEREF];
2253 token = table->next_idx ++;
2255 alloc_table (table, table->rows);
2256 values = table->values + token * MONO_MODULEREF_SIZE;
2257 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2259 token <<= MONO_RESOLUTION_SCOPE_BITS;
2260 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2261 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2266 if (assembly_is_dynamic (image->assembly))
2268 memset (cols, 0, sizeof (cols));
2270 /* image->assembly->image is the manifest module */
2271 image = image->assembly->image;
2272 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2275 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2276 token = table->next_idx ++;
2278 alloc_table (table, table->rows);
2279 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2280 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2281 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2282 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2283 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2284 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2285 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2286 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2287 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2289 if (strcmp ("", image->assembly->aname.culture)) {
2290 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2291 image->assembly->aname.culture);
2294 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2295 guchar pubtoken [9];
2297 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2298 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2300 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2302 token <<= MONO_RESOLUTION_SCOPE_BITS;
2303 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2304 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2309 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2311 MonoDynamicTable *table;
2316 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2319 sigbuffer_init (&buf, 32);
2320 switch (type->type) {
2321 case MONO_TYPE_FNPTR:
2323 case MONO_TYPE_SZARRAY:
2324 case MONO_TYPE_ARRAY:
2326 case MONO_TYPE_MVAR:
2327 case MONO_TYPE_GENERICINST:
2328 encode_type (assembly, type, &buf);
2330 case MONO_TYPE_CLASS:
2331 case MONO_TYPE_VALUETYPE: {
2332 MonoClass *k = mono_class_from_mono_type (type);
2333 if (!k || !k->generic_container) {
2334 sigbuffer_free (&buf);
2337 encode_type (assembly, type, &buf);
2341 sigbuffer_free (&buf);
2345 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2346 if (assembly->save) {
2347 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2348 alloc_table (table, table->rows + 1);
2349 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2350 values [MONO_TYPESPEC_SIGNATURE] = token;
2352 sigbuffer_free (&buf);
2354 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2355 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2361 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2363 MonoDynamicTable *table;
2365 guint32 token, scope, enclosing;
2368 /* if the type requires a typespec, we must try that first*/
2369 if (try_typespec && (token = create_typespec (assembly, type)))
2371 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2374 klass = mono_class_from_mono_type (type);
2376 klass = mono_class_from_mono_type (type);
2379 * If it's in the same module and not a generic type parameter:
2381 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2382 (type->type != MONO_TYPE_MVAR)) {
2383 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2384 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2385 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2389 if (klass->nested_in) {
2390 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2391 /* get the typeref idx of the enclosing type */
2392 enclosing >>= MONO_TYPEDEFORREF_BITS;
2393 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2395 scope = resolution_scope_from_image (assembly, klass->image);
2397 table = &assembly->tables [MONO_TABLE_TYPEREF];
2398 if (assembly->save) {
2399 alloc_table (table, table->rows + 1);
2400 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2401 values [MONO_TYPEREF_SCOPE] = scope;
2402 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2403 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2405 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2406 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2408 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2413 * Despite the name, we handle also TypeSpec (with the above helper).
2416 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2418 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2421 #ifndef DISABLE_REFLECTION_EMIT
2423 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2425 MonoDynamicTable *table;
2427 guint32 token, pclass;
2429 switch (parent & MONO_TYPEDEFORREF_MASK) {
2430 case MONO_TYPEDEFORREF_TYPEREF:
2431 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2433 case MONO_TYPEDEFORREF_TYPESPEC:
2434 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2436 case MONO_TYPEDEFORREF_TYPEDEF:
2437 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2440 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2443 /* extract the index */
2444 parent >>= MONO_TYPEDEFORREF_BITS;
2446 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2448 if (assembly->save) {
2449 alloc_table (table, table->rows + 1);
2450 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2451 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2452 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2453 values [MONO_MEMBERREF_SIGNATURE] = sig;
2456 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2463 * Insert a memberef row into the metadata: the token that point to the memberref
2464 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2465 * mono_image_get_fieldref_token()).
2466 * The sig param is an index to an already built signature.
2469 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2471 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2472 return mono_image_add_memberef_row (assembly, parent, name, sig);
2477 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2480 MonoMethodSignature *sig;
2482 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2484 if (create_typespec) {
2485 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2490 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2491 if (token && !create_typespec)
2494 g_assert (!method->is_inflated);
2497 * A methodref signature can't contain an unmanaged calling convention.
2499 sig = mono_metadata_signature_dup (mono_method_signature (method));
2500 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2501 sig->call_convention = MONO_CALL_DEFAULT;
2502 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2503 method->name, method_encode_signature (assembly, sig));
2505 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2508 if (create_typespec) {
2509 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2510 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2511 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2513 if (assembly->save) {
2516 alloc_table (table, table->rows + 1);
2517 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2518 values [MONO_METHODSPEC_METHOD] = token;
2519 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2522 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2524 /*methodspec and memberef tokens are diferent, */
2525 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2532 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2534 guint32 token, parent, sig;
2535 ReflectionMethodBuilder rmb;
2537 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2539 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2543 name = mono_string_to_utf8 (method->name);
2544 reflection_methodbuilder_from_method_builder (&rmb, method);
2547 * A methodref signature can't contain an unmanaged calling convention.
2548 * Since some flags are encoded as part of call_conv, we need to check against it.
2550 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2551 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2553 sig = method_builder_encode_signature (assembly, &rmb);
2555 if (tb->generic_params)
2556 parent = create_generic_typespec (assembly, tb);
2558 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2560 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2563 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2568 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2569 const gchar *name, guint32 sig)
2571 MonoDynamicTable *table;
2575 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2577 if (assembly->save) {
2578 alloc_table (table, table->rows + 1);
2579 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2580 values [MONO_MEMBERREF_CLASS] = original;
2581 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2582 values [MONO_MEMBERREF_SIGNATURE] = sig;
2585 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2592 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2596 guint32 nparams = mono_array_length (mb->generic_params);
2599 if (!assembly->save)
2602 sigbuffer_init (&buf, 32);
2604 sigbuffer_add_value (&buf, 0xa);
2605 sigbuffer_add_value (&buf, nparams);
2607 for (i = 0; i < nparams; i++) {
2608 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2609 sigbuffer_add_value (&buf, i);
2612 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2613 sigbuffer_free (&buf);
2618 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2620 MonoDynamicTable *table;
2622 guint32 token, mtoken = 0;
2624 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2628 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2630 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2631 switch (mono_metadata_token_table (mtoken)) {
2632 case MONO_TABLE_MEMBERREF:
2633 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2635 case MONO_TABLE_METHOD:
2636 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2639 g_assert_not_reached ();
2642 if (assembly->save) {
2643 alloc_table (table, table->rows + 1);
2644 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2645 values [MONO_METHODSPEC_METHOD] = mtoken;
2646 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2649 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2652 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2657 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2661 if (mb->generic_params && create_methodspec)
2662 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2664 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2668 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2669 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2674 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2676 guint32 token, parent, sig;
2677 ReflectionMethodBuilder rmb;
2679 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2681 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2685 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2687 if (tb->generic_params)
2688 parent = create_generic_typespec (assembly, tb);
2690 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2692 name = mono_string_to_utf8 (rmb.name);
2693 sig = method_builder_encode_signature (assembly, &rmb);
2695 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2698 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2704 is_field_on_inst (MonoClassField *field)
2706 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2710 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2713 get_field_on_inst_generic_type (MonoClassField *field)
2715 MonoClass *class, *gtd;
2716 MonoDynamicGenericClass *dgclass;
2719 g_assert (is_field_on_inst (field));
2721 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2723 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2724 field_index = field - dgclass->fields;
2725 return dgclass->field_generic_types [field_index];
2728 class = field->parent;
2729 gtd = class->generic_class->container_class;
2731 if (field >= class->fields && field - class->fields < class->field.count) {
2732 field_index = field - class->fields;
2733 return gtd->fields [field_index].type;
2736 g_assert_not_reached ();
2740 #ifndef DISABLE_REFLECTION_EMIT
2742 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2748 g_assert (field->parent);
2750 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2754 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2755 int index = field - field->parent->fields;
2756 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2758 if (is_field_on_inst (field))
2759 type = get_field_on_inst_generic_type (field);
2761 type = mono_field_get_type (field);
2763 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2764 mono_field_get_name (field),
2765 fieldref_encode_signature (assembly, field->parent->image, type));
2766 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2771 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2775 MonoGenericClass *gclass;
2776 MonoDynamicGenericClass *dgclass;
2780 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2783 if (is_sre_field_builder (mono_object_class (f->fb))) {
2784 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2785 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2786 klass = mono_class_from_mono_type (type);
2787 gclass = type->data.generic_class;
2788 g_assert (gclass->is_dynamic);
2789 dgclass = (MonoDynamicGenericClass *) gclass;
2791 name = mono_string_to_utf8 (fb->name);
2792 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2793 field_encode_signature (assembly, fb));
2795 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2797 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2799 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2800 klass = mono_class_from_mono_type (type);
2802 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2803 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2805 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2806 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2809 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2814 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2818 MonoGenericClass *gclass;
2821 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2823 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2827 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2828 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2829 MonoDynamicGenericClass *dgclass;
2830 ReflectionMethodBuilder rmb;
2833 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2834 klass = mono_class_from_mono_type (type);
2836 gclass = type->data.generic_class;
2837 g_assert (gclass->is_dynamic);
2838 dgclass = (MonoDynamicGenericClass *) gclass;
2840 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2842 name = mono_string_to_utf8 (rmb.name);
2844 sig = method_builder_encode_signature (assembly, &rmb);
2846 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2848 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2849 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2851 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2852 klass = mono_class_from_mono_type (type);
2854 sig = method_encode_signature (assembly, mono_method_signature (mm));
2855 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2857 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2858 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2862 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2867 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2870 MonoGenericContext tmp_context;
2871 MonoType **type_argv;
2872 MonoGenericInst *ginst;
2873 MonoMethod *method, *inflated;
2876 init_type_builder_generics ((MonoObject*)m->inst);
2878 method = inflate_method (m->inst, (MonoObject*)m->mb);
2880 klass = method->klass;
2882 if (m->method_args == NULL)
2885 if (method->is_inflated)
2886 method = ((MonoMethodInflated *) method)->declaring;
2888 count = mono_array_length (m->method_args);
2890 type_argv = g_new0 (MonoType *, count);
2891 for (i = 0; i < count; i++) {
2892 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2893 type_argv [i] = mono_reflection_type_get_handle (garg);
2895 ginst = mono_metadata_get_generic_inst (count, type_argv);
2898 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2899 tmp_context.method_inst = ginst;
2901 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2906 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2908 guint32 sig, token = 0;
2912 if (m->method_args) {
2913 MonoMethod *inflated;
2915 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2916 if (create_methodspec)
2917 token = mono_image_get_methodspec_token (assembly, inflated);
2919 token = mono_image_get_inflated_method_token (assembly, inflated);
2923 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2927 if (is_sre_method_builder (mono_object_class (m->mb))) {
2928 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2929 MonoGenericClass *gclass;
2930 ReflectionMethodBuilder rmb;
2933 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2934 klass = mono_class_from_mono_type (type);
2935 gclass = type->data.generic_class;
2936 g_assert (gclass->is_dynamic);
2938 reflection_methodbuilder_from_method_builder (&rmb, mb);
2940 name = mono_string_to_utf8 (rmb.name);
2942 sig = method_builder_encode_signature (assembly, &rmb);
2944 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2946 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2947 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2949 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2950 klass = mono_class_from_mono_type (type);
2952 sig = method_encode_signature (assembly, mono_method_signature (mm));
2953 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2955 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2956 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2959 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2964 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2968 guint32 nparams = context->method_inst->type_argc;
2971 if (!assembly->save)
2974 sigbuffer_init (&buf, 32);
2976 * FIXME: vararg, explicit_this, differenc call_conv values...
2978 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2979 sigbuffer_add_value (&buf, nparams);
2981 for (i = 0; i < nparams; i++)
2982 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2984 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2985 sigbuffer_free (&buf);
2990 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2992 MonoDynamicTable *table;
2994 guint32 token, mtoken = 0, sig;
2995 MonoMethodInflated *imethod;
2996 MonoMethod *declaring;
2998 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3000 g_assert (method->is_inflated);
3001 imethod = (MonoMethodInflated *) method;
3002 declaring = imethod->declaring;
3004 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3005 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3007 if (!mono_method_signature (declaring)->generic_param_count)
3010 switch (mono_metadata_token_table (mtoken)) {
3011 case MONO_TABLE_MEMBERREF:
3012 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3014 case MONO_TABLE_METHOD:
3015 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3018 g_assert_not_reached ();
3021 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3023 if (assembly->save) {
3024 alloc_table (table, table->rows + 1);
3025 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3026 values [MONO_METHODSPEC_METHOD] = mtoken;
3027 values [MONO_METHODSPEC_SIGNATURE] = sig;
3030 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3037 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3039 MonoMethodInflated *imethod;
3042 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3046 g_assert (method->is_inflated);
3047 imethod = (MonoMethodInflated *) method;
3049 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3050 token = method_encode_methodspec (assembly, method);
3052 guint32 sig = method_encode_signature (
3053 assembly, mono_method_signature (imethod->declaring));
3054 token = mono_image_get_memberref_token (
3055 assembly, &method->klass->byval_arg, method->name, sig);
3058 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3063 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3065 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3068 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3069 token = mono_image_get_memberref_token (
3070 assembly, &m->klass->byval_arg, m->name, sig);
3076 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3078 MonoDynamicTable *table;
3087 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3088 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3089 * Because of this, we must not insert it into the `typeref' hash table.
3091 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3092 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3096 sigbuffer_init (&buf, 32);
3098 g_assert (tb->generic_params);
3099 klass = mono_class_from_mono_type (type);
3101 if (tb->generic_container)
3102 mono_reflection_create_generic_class (tb);
3104 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3105 g_assert (klass->generic_container);
3106 sigbuffer_add_value (&buf, klass->byval_arg.type);
3107 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3109 count = mono_array_length (tb->generic_params);
3110 sigbuffer_add_value (&buf, count);
3111 for (i = 0; i < count; i++) {
3112 MonoReflectionGenericParam *gparam;
3114 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3116 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3119 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3121 if (assembly->save) {
3122 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3123 alloc_table (table, table->rows + 1);
3124 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3125 values [MONO_TYPESPEC_SIGNATURE] = token;
3127 sigbuffer_free (&buf);
3129 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3130 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3136 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3139 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3141 int i, count, len, pos;
3146 count += mono_array_length (modreq);
3148 count += mono_array_length (modopt);
3151 return mono_metadata_type_dup (NULL, type);
3153 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3155 memcpy (t, type, MONO_SIZEOF_TYPE);
3157 t->num_mods = count;
3160 for (i = 0; i < mono_array_length (modreq); ++i) {
3161 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3162 t->modifiers [pos].required = 1;
3163 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3168 for (i = 0; i < mono_array_length (modopt); ++i) {
3169 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3170 t->modifiers [pos].required = 0;
3171 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3180 init_type_builder_generics (MonoObject *type)
3182 MonoReflectionTypeBuilder *tb;
3184 if (!is_sre_type_builder(mono_object_class (type)))
3186 tb = (MonoReflectionTypeBuilder *)type;
3188 if (tb && tb->generic_container)
3189 mono_reflection_create_generic_class (tb);
3193 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3195 MonoDynamicTable *table;
3197 MonoType *custom = NULL, *type;
3199 guint32 token, pclass, parent, sig;
3202 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3206 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3207 name = mono_string_to_utf8 (fb->name);
3209 /*FIXME this is one more layer of ugliness due how types are created.*/
3210 init_type_builder_generics (fb->type);
3212 /* fb->type does not include the custom modifiers */
3213 /* FIXME: We should do this in one place when a fieldbuilder is created */
3214 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3215 if (fb->modreq || fb->modopt)
3216 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3218 sig = fieldref_encode_signature (assembly, NULL, type);
3221 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3222 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3224 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3225 parent >>= MONO_TYPEDEFORREF_BITS;
3227 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3229 if (assembly->save) {
3230 alloc_table (table, table->rows + 1);
3231 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3232 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3233 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3234 values [MONO_MEMBERREF_SIGNATURE] = sig;
3237 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3239 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3245 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3252 if (!assembly->save)
3255 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3256 g_assert (helper->type == 2);
3258 if (helper->arguments)
3259 nargs = mono_array_length (helper->arguments);
3263 size = 10 + (nargs * 10);
3265 sigbuffer_init (&buf, 32);
3267 /* Encode calling convention */
3268 /* Change Any to Standard */
3269 if ((helper->call_conv & 0x03) == 0x03)
3270 helper->call_conv = 0x01;
3271 /* explicit_this implies has_this */
3272 if (helper->call_conv & 0x40)
3273 helper->call_conv &= 0x20;
3275 if (helper->call_conv == 0) { /* Unmanaged */
3276 idx = helper->unmanaged_call_conv - 1;
3279 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3280 if (helper->call_conv & 0x02) /* varargs */
3284 sigbuffer_add_byte (&buf, idx);
3285 sigbuffer_add_value (&buf, nargs);
3286 encode_reflection_type (assembly, helper->return_type, &buf);
3287 for (i = 0; i < nargs; ++i) {
3288 MonoArray *modreqs = NULL;
3289 MonoArray *modopts = NULL;
3290 MonoReflectionType *pt;
3292 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3293 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3294 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3295 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3297 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3298 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3299 encode_reflection_type (assembly, pt, &buf);
3301 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3302 sigbuffer_free (&buf);
3308 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3311 MonoDynamicTable *table;
3314 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3315 idx = table->next_idx ++;
3317 alloc_table (table, table->rows);
3318 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3320 values [MONO_STAND_ALONE_SIGNATURE] =
3321 mono_reflection_encode_sighelper (assembly, helper);
3327 reflection_cc_to_file (int call_conv) {
3328 switch (call_conv & 0x3) {
3330 case 1: return MONO_CALL_DEFAULT;
3331 case 2: return MONO_CALL_VARARG;
3333 g_assert_not_reached ();
3337 #endif /* !DISABLE_REFLECTION_EMIT */
3341 MonoMethodSignature *sig;
3346 #ifndef DISABLE_REFLECTION_EMIT
3348 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3353 MonoMethodSignature *sig;
3357 name = mono_string_to_utf8 (m->name);
3358 nparams = mono_array_length (m->parameters);
3359 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3361 sig->sentinelpos = -1;
3362 sig->call_convention = reflection_cc_to_file (m->call_conv);
3363 sig->param_count = nparams;
3364 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3365 mtype = mono_reflection_type_get_handle (m->parent);
3366 for (i = 0; i < nparams; ++i)
3367 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3369 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3371 if (strcmp (name, am->name) == 0 &&
3372 mono_metadata_type_equal (am->parent, mtype) &&
3373 mono_metadata_signature_equal (am->sig, sig)) {
3376 m->table_idx = am->token & 0xffffff;
3380 am = g_new0 (ArrayMethod, 1);
3384 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3385 method_encode_signature (assembly, sig));
3386 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3387 m->table_idx = am->token & 0xffffff;
3392 * Insert into the metadata tables all the info about the TypeBuilder tb.
3393 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3396 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3398 MonoDynamicTable *table;
3400 int i, is_object = 0, is_system = 0;
3403 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3404 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3405 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3406 n = mono_string_to_utf8 (tb->name);
3407 if (strcmp (n, "Object") == 0)
3409 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3411 n = mono_string_to_utf8 (tb->nspace);
3412 if (strcmp (n, "System") == 0)
3414 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3416 if (tb->parent && !(is_system && is_object) &&
3417 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3418 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3420 values [MONO_TYPEDEF_EXTENDS] = 0;
3422 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3423 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3426 * if we have explicitlayout or sequentiallayouts, output data in the
3427 * ClassLayout table.
3429 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3430 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3431 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3433 alloc_table (table, table->rows);
3434 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3435 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3436 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3437 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3440 /* handle interfaces */
3441 if (tb->interfaces) {
3442 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3444 table->rows += mono_array_length (tb->interfaces);
3445 alloc_table (table, table->rows);
3446 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3447 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3448 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3449 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3450 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3451 values += MONO_INTERFACEIMPL_SIZE;
3457 table = &assembly->tables [MONO_TABLE_FIELD];
3458 table->rows += tb->num_fields;
3459 alloc_table (table, table->rows);
3460 for (i = 0; i < tb->num_fields; ++i)
3461 mono_image_get_field_info (
3462 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3465 /* handle constructors */
3467 table = &assembly->tables [MONO_TABLE_METHOD];
3468 table->rows += mono_array_length (tb->ctors);
3469 alloc_table (table, table->rows);
3470 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3471 mono_image_get_ctor_info (domain,
3472 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3475 /* handle methods */
3477 table = &assembly->tables [MONO_TABLE_METHOD];
3478 table->rows += tb->num_methods;
3479 alloc_table (table, table->rows);
3480 for (i = 0; i < tb->num_methods; ++i)
3481 mono_image_get_method_info (
3482 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3485 /* Do the same with properties etc.. */
3486 if (tb->events && mono_array_length (tb->events)) {
3487 table = &assembly->tables [MONO_TABLE_EVENT];
3488 table->rows += mono_array_length (tb->events);
3489 alloc_table (table, table->rows);
3490 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3492 alloc_table (table, table->rows);
3493 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3494 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3495 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3496 for (i = 0; i < mono_array_length (tb->events); ++i)
3497 mono_image_get_event_info (
3498 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3500 if (tb->properties && mono_array_length (tb->properties)) {
3501 table = &assembly->tables [MONO_TABLE_PROPERTY];
3502 table->rows += mono_array_length (tb->properties);
3503 alloc_table (table, table->rows);
3504 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3506 alloc_table (table, table->rows);
3507 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3508 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3509 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3510 for (i = 0; i < mono_array_length (tb->properties); ++i)
3511 mono_image_get_property_info (
3512 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3515 /* handle generic parameters */
3516 if (tb->generic_params) {
3517 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3518 table->rows += mono_array_length (tb->generic_params);
3519 alloc_table (table, table->rows);
3520 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3521 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3523 mono_image_get_generic_param_info (
3524 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3528 mono_image_add_decl_security (assembly,
3529 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3532 MonoDynamicTable *ntable;
3534 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3535 ntable->rows += mono_array_length (tb->subtypes);
3536 alloc_table (ntable, ntable->rows);
3537 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3539 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3540 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3542 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3543 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3544 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3545 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3546 mono_string_to_utf8 (tb->name), tb->table_idx,
3547 ntable->next_idx, ntable->rows);*/
3548 values += MONO_NESTED_CLASS_SIZE;
3556 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3560 mono_ptr_array_append (*types, type);
3562 if (!type->subtypes)
3565 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3566 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3567 collect_types (types, subtype);
3572 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3574 if ((*type1)->table_idx < (*type2)->table_idx)
3577 if ((*type1)->table_idx > (*type2)->table_idx)
3584 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3589 for (i = 0; i < mono_array_length (pinfo); ++i) {
3590 MonoReflectionParamBuilder *pb;
3591 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3594 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3599 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3602 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3604 for (i = 0; i < tb->num_fields; ++i) {
3605 MonoReflectionFieldBuilder* fb;
3606 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3607 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3611 for (i = 0; i < mono_array_length (tb->events); ++i) {
3612 MonoReflectionEventBuilder* eb;
3613 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3614 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3617 if (tb->properties) {
3618 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3619 MonoReflectionPropertyBuilder* pb;
3620 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3621 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3625 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3626 MonoReflectionCtorBuilder* cb;
3627 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3628 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3629 params_add_cattrs (assembly, cb->pinfo);
3634 for (i = 0; i < tb->num_methods; ++i) {
3635 MonoReflectionMethodBuilder* mb;
3636 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3637 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3638 params_add_cattrs (assembly, mb->pinfo);
3643 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3644 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3649 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3653 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3655 if (moduleb->global_methods) {
3656 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3657 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3658 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3659 params_add_cattrs (assembly, mb->pinfo);
3663 if (moduleb->global_fields) {
3664 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3665 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3666 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3670 if (moduleb->types) {
3671 for (i = 0; i < moduleb->num_types; ++i)
3672 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3677 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3679 MonoDynamicTable *table;
3683 char *b = blob_size;
3686 table = &assembly->tables [MONO_TABLE_FILE];
3688 alloc_table (table, table->rows);
3689 values = table->values + table->next_idx * MONO_FILE_SIZE;
3690 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3691 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3692 if (image_is_dynamic (module->image)) {
3693 /* This depends on the fact that the main module is emitted last */
3694 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3695 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3698 path = g_strdup (module->image->name);
3700 mono_sha1_get_digest_from_file (path, hash);
3703 mono_metadata_encode_value (20, b, &b);
3704 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3705 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3710 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3712 MonoDynamicTable *table;
3715 table = &assembly->tables [MONO_TABLE_MODULE];
3716 mb->table_idx = table->next_idx ++;
3717 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3718 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3721 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3722 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3723 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3724 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3728 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3729 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3731 MonoDynamicTable *table;
3735 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3736 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3739 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3741 alloc_table (table, table->rows);
3742 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3744 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3745 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3746 if (klass->nested_in)
3747 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3749 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3750 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3751 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3753 res = table->next_idx;
3757 /* Emit nested types */
3758 if (klass->ext && klass->ext->nested_classes) {
3761 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3762 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3769 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3770 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3775 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3777 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3779 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3780 parent_index, assembly);
3784 * We need to do this ourselves since klass->nested_classes is not set up.
3787 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3788 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3793 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3794 guint32 module_index, MonoDynamicImage *assembly)
3796 MonoImage *image = module->image;
3800 t = &image->tables [MONO_TABLE_TYPEDEF];
3802 for (i = 0; i < t->rows; ++i) {
3804 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3805 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3807 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3808 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3813 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3815 MonoDynamicTable *table;
3817 guint32 scope, scope_idx, impl, current_idx;
3818 gboolean forwarder = TRUE;
3819 gpointer iter = NULL;
3822 if (klass->nested_in) {
3823 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3826 scope = resolution_scope_from_image (assembly, klass->image);
3827 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
3828 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
3829 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3832 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3835 alloc_table (table, table->rows);
3836 current_idx = table->next_idx;
3837 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3839 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3840 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3841 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3842 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3843 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3847 while ((nested = mono_class_get_nested_types (klass, &iter)))
3848 add_exported_type (assemblyb, assembly, nested, current_idx);
3852 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3857 if (!assemblyb->type_forwarders)
3860 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3861 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3866 type = mono_reflection_type_get_handle (t);
3869 klass = mono_class_from_mono_type (type);
3871 add_exported_type (assemblyb, assembly, klass, 0);
3875 #define align_pointer(base,p)\
3877 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3879 (p) += 4 - (__diff & 3);\
3883 compare_constants (const void *a, const void *b)
3885 const guint32 *a_values = a;
3886 const guint32 *b_values = b;
3887 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3891 compare_semantics (const void *a, const void *b)
3893 const guint32 *a_values = a;
3894 const guint32 *b_values = b;
3895 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3898 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3902 compare_custom_attrs (const void *a, const void *b)
3904 const guint32 *a_values = a;
3905 const guint32 *b_values = b;
3907 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3911 compare_field_marshal (const void *a, const void *b)
3913 const guint32 *a_values = a;
3914 const guint32 *b_values = b;
3916 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3920 compare_nested (const void *a, const void *b)
3922 const guint32 *a_values = a;
3923 const guint32 *b_values = b;
3925 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3929 compare_genericparam (const void *a, const void *b)
3931 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3932 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3934 if ((*b_entry)->owner == (*a_entry)->owner)
3936 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3937 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3939 return (*a_entry)->owner - (*b_entry)->owner;
3943 compare_declsecurity_attrs (const void *a, const void *b)
3945 const guint32 *a_values = a;
3946 const guint32 *b_values = b;
3948 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3952 compare_interface_impl (const void *a, const void *b)
3954 const guint32 *a_values = a;
3955 const guint32 *b_values = b;
3957 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3961 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3965 pad_heap (MonoDynamicStream *sh)
3967 if (sh->index & 3) {
3968 int sz = 4 - (sh->index & 3);
3969 memset (sh->data + sh->index, 0, sz);
3976 MonoDynamicStream *stream;
3980 * build_compressed_metadata() fills in the blob of data that represents the
3981 * raw metadata as it will be saved in the PE file. The five streams are output
3982 * and the metadata tables are comnpressed from the guint32 array representation,
3983 * to the compressed on-disk format.
3986 build_compressed_metadata (MonoDynamicImage *assembly)
3988 MonoDynamicTable *table;
3990 guint64 valid_mask = 0;
3991 guint64 sorted_mask;
3992 guint32 heapt_size = 0;
3993 guint32 meta_size = 256; /* allow for header and other stuff */
3994 guint32 table_offset;
3995 guint32 ntables = 0;
4001 struct StreamDesc stream_desc [5];
4003 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4004 for (i = 0; i < assembly->gen_params->len; i++){
4005 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4006 write_generic_param_entry (assembly, entry);
4009 stream_desc [0].name = "#~";
4010 stream_desc [0].stream = &assembly->tstream;
4011 stream_desc [1].name = "#Strings";
4012 stream_desc [1].stream = &assembly->sheap;
4013 stream_desc [2].name = "#US";
4014 stream_desc [2].stream = &assembly->us;
4015 stream_desc [3].name = "#Blob";
4016 stream_desc [3].stream = &assembly->blob;
4017 stream_desc [4].name = "#GUID";
4018 stream_desc [4].stream = &assembly->guid;
4020 /* tables that are sorted */
4021 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4022 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4023 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4024 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4025 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4026 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4027 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4029 /* Compute table sizes */
4030 /* the MonoImage has already been created in mono_image_basic_init() */
4031 meta = &assembly->image;
4033 /* sizes should be multiple of 4 */
4034 pad_heap (&assembly->blob);
4035 pad_heap (&assembly->guid);
4036 pad_heap (&assembly->sheap);
4037 pad_heap (&assembly->us);
4039 /* Setup the info used by compute_sizes () */
4040 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4041 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4042 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4044 meta_size += assembly->blob.index;
4045 meta_size += assembly->guid.index;
4046 meta_size += assembly->sheap.index;
4047 meta_size += assembly->us.index;
4049 for (i=0; i < MONO_TABLE_NUM; ++i)
4050 meta->tables [i].rows = assembly->tables [i].rows;
4052 for (i = 0; i < MONO_TABLE_NUM; i++){
4053 if (meta->tables [i].rows == 0)
4055 valid_mask |= (guint64)1 << i;
4057 meta->tables [i].row_size = mono_metadata_compute_size (
4058 meta, i, &meta->tables [i].size_bitfield);
4059 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4061 heapt_size += 24; /* #~ header size */
4062 heapt_size += ntables * 4;
4063 /* make multiple of 4 */
4066 meta_size += heapt_size;
4067 meta->raw_metadata = g_malloc0 (meta_size);
4068 p = (unsigned char*)meta->raw_metadata;
4069 /* the metadata signature */
4070 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4071 /* version numbers and 4 bytes reserved */
4072 int16val = (guint16*)p;
4073 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4074 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4076 /* version string */
4077 int32val = (guint32*)p;
4078 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4080 memcpy (p, meta->version, strlen (meta->version));
4081 p += GUINT32_FROM_LE (*int32val);
4082 align_pointer (meta->raw_metadata, p);
4083 int16val = (guint16*)p;
4084 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4085 *int16val = GUINT16_TO_LE (5); /* number of streams */
4089 * write the stream info.
4091 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4092 table_offset += 3; table_offset &= ~3;
4094 assembly->tstream.index = heapt_size;
4095 for (i = 0; i < 5; ++i) {
4096 int32val = (guint32*)p;
4097 stream_desc [i].stream->offset = table_offset;
4098 *int32val++ = GUINT32_TO_LE (table_offset);
4099 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4100 table_offset += GUINT32_FROM_LE (*int32val);
4101 table_offset += 3; table_offset &= ~3;
4103 strcpy ((char*)p, stream_desc [i].name);
4104 p += strlen (stream_desc [i].name) + 1;
4105 align_pointer (meta->raw_metadata, p);
4108 * now copy the data, the table stream header and contents goes first.
4110 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4111 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4112 int32val = (guint32*)p;
4113 *int32val = GUINT32_TO_LE (0); /* reserved */
4116 *p++ = 2; /* version */
4119 if (meta->idx_string_wide)
4121 if (meta->idx_guid_wide)
4123 if (meta->idx_blob_wide)
4126 *p++ = 1; /* reserved */
4127 int64val = (guint64*)p;
4128 *int64val++ = GUINT64_TO_LE (valid_mask);
4129 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4131 int32val = (guint32*)p;
4132 for (i = 0; i < MONO_TABLE_NUM; i++){
4133 if (meta->tables [i].rows == 0)
4135 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4137 p = (unsigned char*)int32val;
4139 /* sort the tables that still need sorting */
4140 table = &assembly->tables [MONO_TABLE_CONSTANT];
4142 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4143 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4145 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4146 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4148 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4149 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4151 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4152 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4154 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4155 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4156 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4158 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4159 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4161 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4163 /* compress the tables */
4164 for (i = 0; i < MONO_TABLE_NUM; i++){
4167 guint32 bitfield = meta->tables [i].size_bitfield;
4168 if (!meta->tables [i].rows)
4170 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4171 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4172 meta->tables [i].base = (char*)p;
4173 for (row = 1; row <= meta->tables [i].rows; ++row) {
4174 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4175 for (col = 0; col < assembly->tables [i].columns; ++col) {
4176 switch (mono_metadata_table_size (bitfield, col)) {
4178 *p++ = values [col];
4181 *p++ = values [col] & 0xff;
4182 *p++ = (values [col] >> 8) & 0xff;
4185 *p++ = values [col] & 0xff;
4186 *p++ = (values [col] >> 8) & 0xff;
4187 *p++ = (values [col] >> 16) & 0xff;
4188 *p++ = (values [col] >> 24) & 0xff;
4191 g_assert_not_reached ();
4195 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4198 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4199 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4200 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4201 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4202 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4204 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4208 * Some tables in metadata need to be sorted according to some criteria, but
4209 * when methods and fields are first created with reflection, they may be assigned a token
4210 * that doesn't correspond to the final token they will get assigned after the sorting.
4211 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4212 * with the reflection objects that represent them. Once all the tables are set up, the
4213 * reflection objects will contains the correct table index. fixup_method() will fixup the
4214 * tokens for the method with ILGenerator @ilgen.
4217 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4219 guint32 code_idx = GPOINTER_TO_UINT (value);
4220 MonoReflectionILTokenInfo *iltoken;
4221 MonoReflectionFieldBuilder *field;
4222 MonoReflectionCtorBuilder *ctor;
4223 MonoReflectionMethodBuilder *method;
4224 MonoReflectionTypeBuilder *tb;
4225 MonoReflectionArrayMethod *am;
4227 unsigned char *target;
4229 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4230 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4231 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4232 switch (target [3]) {
4233 case MONO_TABLE_FIELD:
4234 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4235 field = (MonoReflectionFieldBuilder *)iltoken->member;
4236 idx = field->table_idx;
4237 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4238 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4239 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4241 g_assert_not_reached ();
4244 case MONO_TABLE_METHOD:
4245 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4246 method = (MonoReflectionMethodBuilder *)iltoken->member;
4247 idx = method->table_idx;
4248 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4249 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4250 idx = ctor->table_idx;
4251 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4252 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4253 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4254 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4256 g_assert_not_reached ();
4259 case MONO_TABLE_TYPEDEF:
4260 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4261 g_assert_not_reached ();
4262 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4263 idx = tb->table_idx;
4265 case MONO_TABLE_MEMBERREF:
4266 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4267 am = (MonoReflectionArrayMethod*)iltoken->member;
4268 idx = am->table_idx;
4269 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4270 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4271 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4272 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4273 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4274 g_assert (m->klass->generic_class || m->klass->generic_container);
4276 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4278 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4279 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4280 g_assert (is_field_on_inst (f));
4282 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4283 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4285 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4287 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4289 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4292 g_assert_not_reached ();
4295 case MONO_TABLE_METHODSPEC:
4296 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4297 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4298 g_assert (mono_method_signature (m)->generic_param_count);
4300 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4302 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4305 g_assert_not_reached ();
4309 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4311 target [0] = idx & 0xff;
4312 target [1] = (idx >> 8) & 0xff;
4313 target [2] = (idx >> 16) & 0xff;
4320 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4321 * value is not known when the table is emitted.
4324 fixup_cattrs (MonoDynamicImage *assembly)
4326 MonoDynamicTable *table;
4328 guint32 type, i, idx, token;
4331 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4333 for (i = 0; i < table->rows; ++i) {
4334 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4336 type = values [MONO_CUSTOM_ATTR_TYPE];
4337 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4338 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4339 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4340 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4343 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4344 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4345 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4346 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4347 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4348 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4349 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4350 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4357 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4359 MonoDynamicTable *table;
4362 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4364 alloc_table (table, table->rows);
4365 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4366 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4367 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4368 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4369 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4374 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4376 MonoDynamicTable *table;
4380 char *b = blob_size;
4382 guint32 idx, offset;
4384 if (rsrc->filename) {
4385 name = mono_string_to_utf8 (rsrc->filename);
4386 sname = g_path_get_basename (name);
4388 table = &assembly->tables [MONO_TABLE_FILE];
4390 alloc_table (table, table->rows);
4391 values = table->values + table->next_idx * MONO_FILE_SIZE;
4392 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4393 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4396 mono_sha1_get_digest_from_file (name, hash);
4397 mono_metadata_encode_value (20, b, &b);
4398 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4399 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4401 idx = table->next_idx++;
4403 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4409 data = mono_array_addr (rsrc->data, char, 0);
4410 len = mono_array_length (rsrc->data);
4416 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4417 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4418 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4419 mono_image_add_stream_data (&assembly->resources, data, len);
4423 * The entry should be emitted into the MANIFESTRESOURCE table of
4424 * the main module, but that needs to reference the FILE table
4425 * which isn't emitted yet.
4432 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4436 set_version_from_string (MonoString *version, guint32 *values)
4438 gchar *ver, *p, *str;
4441 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4442 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4443 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4444 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4447 ver = str = mono_string_to_utf8 (version);
4448 for (i = 0; i < 4; ++i) {
4449 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4455 /* handle Revision and Build */
4465 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4469 char *b = blob_size;
4474 len = mono_array_length (pkey);
4475 mono_metadata_encode_value (len, b, &b);
4476 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4477 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4479 assembly->public_key = g_malloc (len);
4480 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4481 assembly->public_key_len = len;
4483 /* Special case: check for ECMA key (16 bytes) */
4484 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4485 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4486 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4487 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4488 /* minimum key size (in 2.0) is 384 bits */
4489 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4491 /* FIXME - verifier */
4492 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4493 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4495 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4501 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4503 MonoDynamicTable *table;
4504 MonoDynamicImage *assembly;
4505 MonoReflectionAssemblyBuilder *assemblyb;
4509 guint32 module_index;
4511 assemblyb = moduleb->assemblyb;
4512 assembly = moduleb->dynamic_image;
4513 domain = mono_object_domain (assemblyb);
4515 /* Emit ASSEMBLY table */
4516 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4517 alloc_table (table, 1);
4518 values = table->values + MONO_ASSEMBLY_SIZE;
4519 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4520 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4521 if (assemblyb->culture) {
4522 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4524 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4526 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4527 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4528 set_version_from_string (assemblyb->version, values);
4530 /* Emit FILE + EXPORTED_TYPE table */
4532 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4534 MonoReflectionModuleBuilder *file_module =
4535 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4536 if (file_module != moduleb) {
4537 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4539 if (file_module->types) {
4540 for (j = 0; j < file_module->num_types; ++j) {
4541 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4542 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4547 if (assemblyb->loaded_modules) {
4548 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4549 MonoReflectionModule *file_module =
4550 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4551 mono_image_fill_file_table (domain, file_module, assembly);
4553 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4556 if (assemblyb->type_forwarders)
4557 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4559 /* Emit MANIFESTRESOURCE table */
4561 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4563 MonoReflectionModuleBuilder *file_module =
4564 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4565 /* The table for the main module is emitted later */
4566 if (file_module != moduleb) {
4568 if (file_module->resources) {
4569 int len = mono_array_length (file_module->resources);
4570 for (j = 0; j < len; ++j) {
4571 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4572 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4579 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4582 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4583 * for the modulebuilder @moduleb.
4584 * At the end of the process, method and field tokens are fixed up and the
4585 * on-disk compressed metadata representation is created.
4588 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4590 MonoDynamicTable *table;
4591 MonoDynamicImage *assembly;
4592 MonoReflectionAssemblyBuilder *assemblyb;
4598 assemblyb = moduleb->assemblyb;
4599 assembly = moduleb->dynamic_image;
4600 domain = mono_object_domain (assemblyb);
4602 if (assembly->text_rva)
4605 assembly->text_rva = START_TEXT_RVA;
4607 if (moduleb->is_main) {
4608 mono_image_emit_manifest (moduleb);
4611 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4612 table->rows = 1; /* .<Module> */
4614 alloc_table (table, table->rows);
4616 * Set the first entry.
4618 values = table->values + table->columns;
4619 values [MONO_TYPEDEF_FLAGS] = 0;
4620 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4621 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4622 values [MONO_TYPEDEF_EXTENDS] = 0;
4623 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4624 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4627 * handle global methods
4628 * FIXME: test what to do when global methods are defined in multiple modules.
4630 if (moduleb->global_methods) {
4631 table = &assembly->tables [MONO_TABLE_METHOD];
4632 table->rows += mono_array_length (moduleb->global_methods);
4633 alloc_table (table, table->rows);
4634 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4635 mono_image_get_method_info (
4636 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4638 if (moduleb->global_fields) {
4639 table = &assembly->tables [MONO_TABLE_FIELD];
4640 table->rows += mono_array_length (moduleb->global_fields);
4641 alloc_table (table, table->rows);
4642 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4643 mono_image_get_field_info (
4644 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4647 table = &assembly->tables [MONO_TABLE_MODULE];
4648 alloc_table (table, 1);
4649 mono_image_fill_module_table (domain, moduleb, assembly);
4651 /* Collect all types into a list sorted by their table_idx */
4652 mono_ptr_array_init (types, moduleb->num_types);
4655 for (i = 0; i < moduleb->num_types; ++i) {
4656 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4657 collect_types (&types, type);
4660 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4661 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4662 table->rows += mono_ptr_array_size (types);
4663 alloc_table (table, table->rows);
4666 * Emit type names + namespaces at one place inside the string heap,
4667 * so load_class_names () needs to touch fewer pages.
4669 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4671 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4673 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4674 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4675 string_heap_insert_mstring (&assembly->sheap, tb->name);
4678 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4679 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4680 mono_image_get_type_info (domain, type, assembly);
4684 * table->rows is already set above and in mono_image_fill_module_table.
4686 /* add all the custom attributes at the end, once all the indexes are stable */
4687 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4689 /* CAS assembly permissions */
4690 if (assemblyb->permissions_minimum)
4691 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4692 if (assemblyb->permissions_optional)
4693 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4694 if (assemblyb->permissions_refused)
4695 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4697 module_add_cattrs (assembly, moduleb);
4700 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4702 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4703 * the final tokens and don't need another fixup pass. */
4705 if (moduleb->global_methods) {
4706 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4707 MonoReflectionMethodBuilder *mb = mono_array_get (
4708 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4709 mono_image_add_methodimpl (assembly, mb);
4713 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4714 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4715 if (type->methods) {
4716 for (j = 0; j < type->num_methods; ++j) {
4717 MonoReflectionMethodBuilder *mb = mono_array_get (
4718 type->methods, MonoReflectionMethodBuilder*, j);
4720 mono_image_add_methodimpl (assembly, mb);
4725 mono_ptr_array_destroy (types);
4727 fixup_cattrs (assembly);
4730 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4733 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4735 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4738 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4742 guint32 import_lookup_table;
4746 guint32 import_address_table_rva;
4754 #ifndef DISABLE_REFLECTION_EMIT
4757 * mono_image_insert_string:
4758 * @module: module builder object
4761 * Insert @str into the user string stream of @module.
4764 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4766 MonoDynamicImage *assembly;
4771 MONO_ARCH_SAVE_REGS;
4773 if (!module->dynamic_image)
4774 mono_image_module_basic_init (module);
4776 assembly = module->dynamic_image;
4778 if (assembly->save) {
4779 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4780 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4781 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4783 char *swapped = g_malloc (2 * mono_string_length (str));
4784 const char *p = (const char*)mono_string_chars (str);
4786 swap_with_size (swapped, p, 2, mono_string_length (str));
4787 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4791 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4793 mono_image_add_stream_data (&assembly->us, "", 1);
4795 idx = assembly->us.index ++;
4798 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4800 return MONO_TOKEN_STRING | idx;
4804 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4808 MonoMethodSignature *sig;
4810 klass = obj->vtable->klass;
4811 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4812 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4813 MonoMethodSignature *old;
4814 guint32 sig_token, parent;
4817 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4819 nargs = mono_array_length (opt_param_types);
4820 old = mono_method_signature (method);
4821 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4823 sig->hasthis = old->hasthis;
4824 sig->explicit_this = old->explicit_this;
4825 sig->call_convention = old->call_convention;
4826 sig->generic_param_count = old->generic_param_count;
4827 sig->param_count = old->param_count + nargs;
4828 sig->sentinelpos = old->param_count;
4829 sig->ret = old->ret;
4831 for (i = 0; i < old->param_count; i++)
4832 sig->params [i] = old->params [i];
4834 for (i = 0; i < nargs; i++) {
4835 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4836 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4839 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4840 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4841 parent >>= MONO_TYPEDEFORREF_BITS;
4843 parent <<= MONO_MEMBERREF_PARENT_BITS;
4844 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4846 sig_token = method_encode_signature (assembly, sig);
4847 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4848 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4849 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4850 ReflectionMethodBuilder rmb;
4851 guint32 parent, sig_token;
4852 int nopt_args, nparams, ngparams, i;
4855 reflection_methodbuilder_from_method_builder (&rmb, mb);
4856 rmb.opt_types = opt_param_types;
4857 nopt_args = mono_array_length (opt_param_types);
4859 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4860 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4861 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4863 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4864 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4865 sig->call_convention = rmb.call_conv;
4866 sig->generic_param_count = ngparams;
4867 sig->param_count = nparams + nopt_args;
4868 sig->sentinelpos = nparams;
4869 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4871 for (i = 0; i < nparams; i++) {
4872 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4873 sig->params [i] = mono_reflection_type_get_handle (rt);
4876 for (i = 0; i < nopt_args; i++) {
4877 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4878 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4881 sig_token = method_builder_encode_signature (assembly, &rmb);
4883 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4884 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4886 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4887 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4889 name = mono_string_to_utf8 (rmb.name);
4890 token = mono_image_get_varargs_method_token (
4891 assembly, parent, name, sig_token);
4894 g_error ("requested method token for %s\n", klass->name);
4897 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4898 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4903 * mono_image_create_token:
4904 * @assembly: a dynamic assembly
4906 * @register_token: Whenever to register the token in the assembly->tokens hash.
4908 * Get a token to insert in the IL code stream for the given MemberInfo.
4909 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4910 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4914 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4915 gboolean create_open_instance, gboolean register_token)
4920 klass = obj->vtable->klass;
4922 /* Check for user defined reflection objects */
4923 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4924 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4925 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4927 if (strcmp (klass->name, "MethodBuilder") == 0) {
4928 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4929 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4931 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4932 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4934 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4935 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4936 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4937 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4938 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4940 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4941 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4943 token = mono_image_get_ctorbuilder_token (assembly, mb);
4944 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4945 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4946 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4947 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4948 if (tb->generic_params) {
4949 token = mono_image_get_generic_field_token (assembly, fb);
4951 if (tb->module->dynamic_image == assembly) {
4952 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4954 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4957 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4958 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4959 if (create_open_instance && tb->generic_params) {
4961 init_type_builder_generics (obj);
4962 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4963 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4964 token = mono_metadata_token_from_dor (token);
4965 } else if (tb->module->dynamic_image == assembly) {
4966 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4969 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4970 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4972 } else if (strcmp (klass->name, "MonoType") == 0) {
4973 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4974 MonoClass *mc = mono_class_from_mono_type (type);
4975 token = mono_metadata_token_from_dor (
4976 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4977 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4978 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979 token = mono_metadata_token_from_dor (
4980 mono_image_typedef_or_ref (assembly, type));
4981 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4982 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4983 token = mono_metadata_token_from_dor (
4984 mono_image_typedef_or_ref (assembly, type));
4985 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4986 strcmp (klass->name, "MonoMethod") == 0 ||
4987 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4988 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4989 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4990 if (m->method->is_inflated) {
4991 if (create_open_instance)
4992 token = mono_image_get_methodspec_token (assembly, m->method);
4994 token = mono_image_get_inflated_method_token (assembly, m->method);
4995 } else if ((m->method->klass->image == &assembly->image) &&
4996 !m->method->klass->generic_class) {
4997 static guint32 method_table_idx = 0xffffff;
4998 if (m->method->klass->wastypebuilder) {
4999 /* we use the same token as the one that was assigned
5000 * to the Methodbuilder.
5001 * FIXME: do the equivalent for Fields.
5003 token = m->method->token;
5006 * Each token should have a unique index, but the indexes are
5007 * assigned by managed code, so we don't know about them. An
5008 * easy solution is to count backwards...
5010 method_table_idx --;
5011 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5014 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5016 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5017 } else if (strcmp (klass->name, "MonoField") == 0) {
5018 MonoReflectionField *f = (MonoReflectionField *)obj;
5019 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5020 static guint32 field_table_idx = 0xffffff;
5022 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5024 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5026 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5027 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5028 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5029 token = mono_image_get_array_token (assembly, m);
5030 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5031 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5032 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5033 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5034 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5035 token = mono_metadata_token_from_dor (
5036 mono_image_typedef_or_ref (assembly, type));
5037 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5038 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5039 token = mono_image_get_field_on_inst_token (assembly, f);
5040 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5041 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5042 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5043 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5044 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5045 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5046 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5047 MonoReflectionType *type = (MonoReflectionType *)obj;
5048 token = mono_metadata_token_from_dor (
5049 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5051 g_error ("requested token for %s\n", klass->name);
5055 mono_image_register_token (assembly, token, obj);
5061 * mono_image_register_token:
5063 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5064 * the Module.ResolveXXXToken () methods to work.
5067 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5069 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5071 /* There could be multiple MethodInfo objects with the same token */
5072 //g_assert (prev == obj);
5074 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5078 static MonoDynamicImage*
5079 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5081 static const guchar entrycode [16] = {0xff, 0x25, 0};
5082 MonoDynamicImage *image;
5085 const char *version;
5087 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5088 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5090 version = mono_get_runtime_info ()->runtime_version;
5093 /* The MonoGHashTable's need GC tracking */
5094 image = GC_MALLOC (sizeof (MonoDynamicImage));
5096 image = g_new0 (MonoDynamicImage, 1);
5099 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5101 /*g_print ("created image %p\n", image);*/
5102 /* keep in sync with image.c */
5103 image->image.name = assembly_name;
5104 image->image.assembly_name = image->image.name; /* they may be different */
5105 image->image.module_name = module_name;
5106 image->image.version = g_strdup (version);
5107 image->image.md_version_major = 1;
5108 image->image.md_version_minor = 1;
5109 image->image.dynamic = TRUE;
5111 image->image.references = g_new0 (MonoAssembly*, 1);
5112 image->image.references [0] = NULL;
5114 mono_image_init (&image->image);
5116 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5117 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5118 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5119 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5120 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5121 image->handleref = g_hash_table_new (NULL, NULL);
5122 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5123 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5124 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5125 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5126 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5127 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5128 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5129 image->gen_params = g_ptr_array_new ();
5130 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5132 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5133 string_heap_init (&image->sheap);
5134 mono_image_add_stream_data (&image->us, "", 1);
5135 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5136 /* import tables... */
5137 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5138 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5139 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5140 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5141 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5142 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5143 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5144 stream_data_align (&image->code);
5146 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5148 for (i=0; i < MONO_TABLE_NUM; ++i) {
5149 image->tables [i].next_idx = 1;
5150 image->tables [i].columns = table_sizes [i];
5153 image->image.assembly = (MonoAssembly*)assembly;
5154 image->run = assembly->run;
5155 image->save = assembly->save;
5156 image->pe_kind = 0x1; /* ILOnly */
5157 image->machine = 0x14c; /* I386 */
5159 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5166 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5172 release_hashtable (MonoGHashTable **hash)
5175 mono_g_hash_table_destroy (*hash);
5181 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5183 release_hashtable (&image->token_fixups);
5184 release_hashtable (&image->handleref_managed);
5185 release_hashtable (&image->tokens);
5186 release_hashtable (&image->remapped_tokens);
5187 release_hashtable (&image->generic_def_objects);
5188 release_hashtable (&image->methodspec);
5192 mono_dynamic_image_free (MonoDynamicImage *image)
5194 MonoDynamicImage *di = image;
5199 mono_g_hash_table_destroy (di->methodspec);
5201 g_hash_table_destroy (di->typespec);
5203 g_hash_table_destroy (di->typeref);
5205 g_hash_table_destroy (di->handleref);
5206 if (di->handleref_managed)
5207 mono_g_hash_table_destroy (di->handleref_managed);
5209 mono_g_hash_table_destroy (di->tokens);
5210 if (di->remapped_tokens)
5211 mono_g_hash_table_destroy (di->remapped_tokens);
5212 if (di->generic_def_objects)
5213 mono_g_hash_table_destroy (di->generic_def_objects);
5214 if (di->blob_cache) {
5215 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5216 g_hash_table_destroy (di->blob_cache);
5218 if (di->standalonesig_cache)
5219 g_hash_table_destroy (di->standalonesig_cache);
5220 for (list = di->array_methods; list; list = list->next) {
5221 ArrayMethod *am = (ArrayMethod *)list->data;
5226 g_list_free (di->array_methods);
5227 if (di->gen_params) {
5228 for (i = 0; i < di->gen_params->len; i++) {
5229 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5230 mono_gc_deregister_root ((char*) &entry->gparam);
5233 g_ptr_array_free (di->gen_params, TRUE);
5235 if (di->token_fixups)
5236 mono_g_hash_table_destroy (di->token_fixups);
5237 if (di->method_to_table_idx)
5238 g_hash_table_destroy (di->method_to_table_idx);
5239 if (di->field_to_table_idx)
5240 g_hash_table_destroy (di->field_to_table_idx);
5241 if (di->method_aux_hash)
5242 g_hash_table_destroy (di->method_aux_hash);
5243 if (di->vararg_aux_hash)
5244 g_hash_table_destroy (di->vararg_aux_hash);
5245 g_free (di->strong_name);
5246 g_free (di->win32_res);
5248 g_free (di->public_key);
5250 /*g_print ("string heap destroy for image %p\n", di);*/
5251 mono_dynamic_stream_reset (&di->sheap);
5252 mono_dynamic_stream_reset (&di->code);
5253 mono_dynamic_stream_reset (&di->resources);
5254 mono_dynamic_stream_reset (&di->us);
5255 mono_dynamic_stream_reset (&di->blob);
5256 mono_dynamic_stream_reset (&di->tstream);
5257 mono_dynamic_stream_reset (&di->guid);
5258 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5259 g_free (di->tables [i].values);
5264 mono_dynamic_image_free_image (MonoDynamicImage *image)
5266 /* See create_dynamic_mono_image () */
5268 /* Allocated using GC_MALLOC */
5274 #ifndef DISABLE_REFLECTION_EMIT
5277 * mono_image_basic_init:
5278 * @assembly: an assembly builder object
5280 * Create the MonoImage that represents the assembly builder and setup some
5281 * of the helper hash table and the basic metadata streams.
5284 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5286 MonoDynamicAssembly *assembly;
5287 MonoDynamicImage *image;
5288 MonoDomain *domain = mono_object_domain (assemblyb);
5290 MONO_ARCH_SAVE_REGS;
5292 if (assemblyb->dynamic_assembly)
5296 /* assembly->assembly.image might be GC allocated */
5297 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5299 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5302 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5304 assembly->assembly.ref_count = 1;
5305 assembly->assembly.dynamic = TRUE;
5306 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5307 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5308 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5309 if (assemblyb->culture)
5310 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5312 assembly->assembly.aname.culture = g_strdup ("");
5314 if (assemblyb->version) {
5315 char *vstr = mono_string_to_utf8 (assemblyb->version);
5316 char **version = g_strsplit (vstr, ".", 4);
5317 char **parts = version;
5318 assembly->assembly.aname.major = atoi (*parts++);
5319 assembly->assembly.aname.minor = atoi (*parts++);
5320 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5321 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5323 g_strfreev (version);
5326 assembly->assembly.aname.major = 0;
5327 assembly->assembly.aname.minor = 0;
5328 assembly->assembly.aname.build = 0;
5329 assembly->assembly.aname.revision = 0;
5332 assembly->run = assemblyb->access != 2;
5333 assembly->save = assemblyb->access != 1;
5334 assembly->domain = domain;
5336 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5337 image->initial_image = TRUE;
5338 assembly->assembly.aname.name = image->image.name;
5339 assembly->assembly.image = &image->image;
5340 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5341 /* -1 to correct for the trailing NULL byte */
5342 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5343 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5345 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5348 mono_domain_assemblies_lock (domain);
5349 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5350 mono_domain_assemblies_unlock (domain);
5352 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5354 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5356 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5359 #endif /* !DISABLE_REFLECTION_EMIT */
5361 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5364 calc_section_size (MonoDynamicImage *assembly)
5368 /* alignment constraints */
5369 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5370 g_assert ((assembly->code.index % 4) == 0);
5371 assembly->meta_size += 3;
5372 assembly->meta_size &= ~3;
5373 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5374 g_assert ((assembly->resources.index % 4) == 0);
5376 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5377 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5380 if (assembly->win32_res) {
5381 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5383 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5384 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5388 assembly->sections [MONO_SECTION_RELOC].size = 12;
5389 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5399 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5403 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5405 ResTreeNode *t1 = (ResTreeNode*)a;
5406 ResTreeNode *t2 = (ResTreeNode*)b;
5408 return t1->id - t2->id;
5412 * resource_tree_create:
5414 * Organize the resources into a resource tree.
5416 static ResTreeNode *
5417 resource_tree_create (MonoArray *win32_resources)
5419 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5423 tree = g_new0 (ResTreeNode, 1);
5425 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5426 MonoReflectionWin32Resource *win32_res =
5427 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5431 /* FIXME: BUG: this stores managed references in unmanaged memory */
5432 lang_node = g_new0 (ResTreeNode, 1);
5433 lang_node->id = win32_res->lang_id;
5434 lang_node->win32_res = win32_res;
5436 /* Create type node if neccesary */
5438 for (l = tree->children; l; l = l->next)
5439 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5440 type_node = (ResTreeNode*)l->data;
5445 type_node = g_new0 (ResTreeNode, 1);
5446 type_node->id = win32_res->res_type;
5449 * The resource types have to be sorted otherwise
5450 * Windows Explorer can't display the version information.
5452 tree->children = g_slist_insert_sorted (tree->children,
5453 type_node, resource_tree_compare_by_id);
5456 /* Create res node if neccesary */
5458 for (l = type_node->children; l; l = l->next)
5459 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5460 res_node = (ResTreeNode*)l->data;
5465 res_node = g_new0 (ResTreeNode, 1);
5466 res_node->id = win32_res->res_id;
5467 type_node->children = g_slist_append (type_node->children, res_node);
5470 res_node->children = g_slist_append (res_node->children, lang_node);
5477 * resource_tree_encode:
5479 * Encode the resource tree into the format used in the PE file.
5482 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5485 MonoPEResourceDir dir;
5486 MonoPEResourceDirEntry dir_entry;
5487 MonoPEResourceDataEntry data_entry;
5489 guint32 res_id_entries;
5492 * For the format of the resource directory, see the article
5493 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5497 memset (&dir, 0, sizeof (dir));
5498 memset (&dir_entry, 0, sizeof (dir_entry));
5499 memset (&data_entry, 0, sizeof (data_entry));
5501 g_assert (sizeof (dir) == 16);
5502 g_assert (sizeof (dir_entry) == 8);
5503 g_assert (sizeof (data_entry) == 16);
5505 node->offset = p - begin;
5507 /* IMAGE_RESOURCE_DIRECTORY */
5508 res_id_entries = g_slist_length (node->children);
5509 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5511 memcpy (p, &dir, sizeof (dir));
5514 /* Reserve space for entries */
5516 p += sizeof (dir_entry) * res_id_entries;
5518 /* Write children */
5519 for (l = node->children; l; l = l->next) {
5520 ResTreeNode *child = (ResTreeNode*)l->data;
5522 if (child->win32_res) {
5525 child->offset = p - begin;
5527 /* IMAGE_RESOURCE_DATA_ENTRY */
5528 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5529 size = mono_array_length (child->win32_res->res_data);
5530 data_entry.rde_size = GUINT32_TO_LE (size);
5532 memcpy (p, &data_entry, sizeof (data_entry));
5533 p += sizeof (data_entry);
5535 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5538 resource_tree_encode (child, begin, p, &p);
5542 /* IMAGE_RESOURCE_ENTRY */
5543 for (l = node->children; l; l = l->next) {
5544 ResTreeNode *child = (ResTreeNode*)l->data;
5546 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5547 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5549 memcpy (entries, &dir_entry, sizeof (dir_entry));
5550 entries += sizeof (dir_entry);
5557 resource_tree_free (ResTreeNode * node)
5560 for (list = node->children; list; list = list->next)
5561 resource_tree_free ((ResTreeNode*)list->data);
5562 g_slist_free(node->children);
5567 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5572 MonoReflectionWin32Resource *win32_res;
5575 if (!assemblyb->win32_resources)
5579 * Resources are stored in a three level tree inside the PE file.
5580 * - level one contains a node for each type of resource
5581 * - level two contains a node for each resource
5582 * - level three contains a node for each instance of a resource for a
5583 * specific language.
5586 tree = resource_tree_create (assemblyb->win32_resources);
5588 /* Estimate the size of the encoded tree */
5590 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5591 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5592 size += mono_array_length (win32_res->res_data);
5594 /* Directory structure */
5595 size += mono_array_length (assemblyb->win32_resources) * 256;
5596 p = buf = g_malloc (size);
5598 resource_tree_encode (tree, p, p, &p);
5600 g_assert (p - buf <= size);
5602 assembly->win32_res = g_malloc (p - buf);
5603 assembly->win32_res_size = p - buf;
5604 memcpy (assembly->win32_res, buf, p - buf);
5607 resource_tree_free (tree);
5611 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5613 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5616 p += sizeof (MonoPEResourceDir);
5617 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5618 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5619 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5620 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5621 fixup_resource_directory (res_section, child, rva);
5623 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5624 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5627 p += sizeof (MonoPEResourceDirEntry);
5632 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5635 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5636 g_error ("WriteFile returned %d\n", GetLastError ());
5640 * mono_image_create_pefile:
5641 * @mb: a module builder object
5643 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5644 * assembly->pefile where it can be easily retrieved later in chunks.
5647 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5649 MonoMSDOSHeader *msdos;
5650 MonoDotNetHeader *header;
5651 MonoSectionTable *section;
5652 MonoCLIHeader *cli_header;
5653 guint32 size, image_size, virtual_base, text_offset;
5654 guint32 header_start, section_start, file_offset, virtual_offset;
5655 MonoDynamicImage *assembly;
5656 MonoReflectionAssemblyBuilder *assemblyb;
5657 MonoDynamicStream pefile_stream = {0};
5658 MonoDynamicStream *pefile = &pefile_stream;
5660 guint32 *rva, value;
5662 static const unsigned char msheader[] = {
5663 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5664 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5667 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5668 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5669 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5670 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5673 assemblyb = mb->assemblyb;
5675 mono_image_basic_init (assemblyb);
5676 assembly = mb->dynamic_image;
5678 assembly->pe_kind = assemblyb->pe_kind;
5679 assembly->machine = assemblyb->machine;
5680 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5681 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5683 mono_image_build_metadata (mb);
5685 if (mb->is_main && assemblyb->resources) {
5686 int len = mono_array_length (assemblyb->resources);
5687 for (i = 0; i < len; ++i)
5688 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5691 if (mb->resources) {
5692 int len = mono_array_length (mb->resources);
5693 for (i = 0; i < len; ++i)
5694 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5697 build_compressed_metadata (assembly);
5700 assembly_add_win32_resources (assembly, assemblyb);
5702 nsections = calc_section_size (assembly);
5704 /* The DOS header and stub */
5705 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5706 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5708 /* the dotnet header */
5709 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5711 /* the section tables */
5712 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5714 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5715 virtual_offset = VIRT_ALIGN;
5718 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5719 if (!assembly->sections [i].size)
5722 file_offset += FILE_ALIGN - 1;
5723 file_offset &= ~(FILE_ALIGN - 1);
5724 virtual_offset += VIRT_ALIGN - 1;
5725 virtual_offset &= ~(VIRT_ALIGN - 1);
5727 assembly->sections [i].offset = file_offset;
5728 assembly->sections [i].rva = virtual_offset;
5730 file_offset += assembly->sections [i].size;
5731 virtual_offset += assembly->sections [i].size;
5732 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5735 file_offset += FILE_ALIGN - 1;
5736 file_offset &= ~(FILE_ALIGN - 1);
5738 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5740 /* back-patch info */
5741 msdos = (MonoMSDOSHeader*)pefile->data;
5742 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5744 header = (MonoDotNetHeader*)(pefile->data + header_start);
5745 header->pesig [0] = 'P';
5746 header->pesig [1] = 'E';
5748 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5749 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5750 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5751 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5752 if (assemblyb->pekind == 1) {
5754 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5757 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5760 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5762 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5763 header->pe.pe_major = 6;
5764 header->pe.pe_minor = 0;
5765 size = assembly->sections [MONO_SECTION_TEXT].size;
5766 size += FILE_ALIGN - 1;
5767 size &= ~(FILE_ALIGN - 1);
5768 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5769 size = assembly->sections [MONO_SECTION_RSRC].size;
5770 size += FILE_ALIGN - 1;
5771 size &= ~(FILE_ALIGN - 1);
5772 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5773 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5774 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5775 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5776 /* pe_rva_entry_point always at the beginning of the text section */
5777 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5779 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5780 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5781 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5782 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5783 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5784 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5785 size = section_start;
5786 size += FILE_ALIGN - 1;
5787 size &= ~(FILE_ALIGN - 1);
5788 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5790 size += VIRT_ALIGN - 1;
5791 size &= ~(VIRT_ALIGN - 1);
5792 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5795 // Translate the PEFileKind value to the value expected by the Windows loader
5801 // PEFileKinds.Dll == 1
5802 // PEFileKinds.ConsoleApplication == 2
5803 // PEFileKinds.WindowApplication == 3
5806 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5807 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5809 if (assemblyb->pekind == 3)
5814 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5816 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5817 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5818 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5819 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5820 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5821 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5823 /* fill data directory entries */
5825 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5826 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5828 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5829 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5831 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5832 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5833 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5834 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5835 /* patch entrypoint name */
5836 if (assemblyb->pekind == 1)
5837 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5839 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5840 /* patch imported function RVA name */
5841 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5842 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5844 /* the import table */
5845 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5846 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5847 /* patch imported dll RVA name and other entries in the dir */
5848 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5849 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5850 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5851 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5852 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5853 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5855 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5856 value = (assembly->text_rva + assembly->imp_names_offset);
5857 *p++ = (value) & 0xff;
5858 *p++ = (value >> 8) & (0xff);
5859 *p++ = (value >> 16) & (0xff);
5860 *p++ = (value >> 24) & (0xff);
5862 /* the CLI header info */
5863 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5864 cli_header->ch_size = GUINT32_FROM_LE (72);
5865 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5866 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5867 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5868 if (assemblyb->entry_point) {
5869 guint32 table_idx = 0;
5870 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5871 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5872 table_idx = methodb->table_idx;
5874 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5876 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5878 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5880 /* The embedded managed resources */
5881 text_offset = assembly->text_rva + assembly->code.index;
5882 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5883 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5884 text_offset += assembly->resources.index;
5885 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5886 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5887 text_offset += assembly->meta_size;
5888 if (assembly->strong_name_size) {
5889 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5890 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5891 text_offset += assembly->strong_name_size;
5894 /* write the section tables and section content */
5895 section = (MonoSectionTable*)(pefile->data + section_start);
5896 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5897 static const char section_names [][7] = {
5898 ".text", ".rsrc", ".reloc"
5900 if (!assembly->sections [i].size)
5902 strcpy (section->st_name, section_names [i]);
5903 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5904 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5905 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5906 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5907 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5908 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5909 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5913 checked_write_file (file, pefile->data, pefile->index);
5915 mono_dynamic_stream_reset (pefile);
5917 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5918 if (!assembly->sections [i].size)
5921 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5922 g_error ("SetFilePointer returned %d\n", GetLastError ());
5925 case MONO_SECTION_TEXT:
5926 /* patch entry point */
5927 p = (guchar*)(assembly->code.data + 2);
5928 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5929 *p++ = (value) & 0xff;
5930 *p++ = (value >> 8) & 0xff;
5931 *p++ = (value >> 16) & 0xff;
5932 *p++ = (value >> 24) & 0xff;
5934 checked_write_file (file, assembly->code.data, assembly->code.index);
5935 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5936 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5937 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5940 g_free (assembly->image.raw_metadata);
5942 case MONO_SECTION_RELOC: {
5946 guint16 type_and_offset;
5950 g_assert (sizeof (reloc) == 12);
5952 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5953 reloc.block_size = GUINT32_FROM_LE (12);
5956 * the entrypoint is always at the start of the text section
5957 * 3 is IMAGE_REL_BASED_HIGHLOW
5958 * 2 is patch_size_rva - text_rva
5960 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5963 checked_write_file (file, &reloc, sizeof (reloc));
5967 case MONO_SECTION_RSRC:
5968 if (assembly->win32_res) {
5970 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5971 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5972 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5976 g_assert_not_reached ();
5980 /* check that the file is properly padded */
5981 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5982 g_error ("SetFilePointer returned %d\n", GetLastError ());
5983 if (! SetEndOfFile (file))
5984 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5986 mono_dynamic_stream_reset (&assembly->code);
5987 mono_dynamic_stream_reset (&assembly->us);
5988 mono_dynamic_stream_reset (&assembly->blob);
5989 mono_dynamic_stream_reset (&assembly->guid);
5990 mono_dynamic_stream_reset (&assembly->sheap);
5992 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5993 g_hash_table_destroy (assembly->blob_cache);
5994 assembly->blob_cache = NULL;
5997 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6000 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6002 g_assert_not_reached ();
6005 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6007 #ifndef DISABLE_REFLECTION_EMIT
6009 MonoReflectionModule *
6010 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6014 MonoImageOpenStatus status;
6015 MonoDynamicAssembly *assembly;
6016 guint32 module_count;
6017 MonoImage **new_modules;
6018 gboolean *new_modules_loaded;
6020 name = mono_string_to_utf8 (fileName);
6022 image = mono_image_open (name, &status);
6025 if (status == MONO_IMAGE_ERROR_ERRNO)
6026 exc = mono_get_exception_file_not_found (fileName);
6028 exc = mono_get_exception_bad_image_format (name);
6030 mono_raise_exception (exc);
6035 assembly = ab->dynamic_assembly;
6036 image->assembly = (MonoAssembly*)assembly;
6038 module_count = image->assembly->image->module_count;
6039 new_modules = g_new0 (MonoImage *, module_count + 1);
6040 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6042 if (image->assembly->image->modules)
6043 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6044 if (image->assembly->image->modules_loaded)
6045 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6046 new_modules [module_count] = image;
6047 new_modules_loaded [module_count] = TRUE;
6048 mono_image_addref (image);
6050 g_free (image->assembly->image->modules);
6051 image->assembly->image->modules = new_modules;
6052 image->assembly->image->modules_loaded = new_modules_loaded;
6053 image->assembly->image->module_count ++;
6055 mono_assembly_load_references (image, &status);
6057 mono_image_close (image);
6058 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6061 return mono_module_get_object (mono_domain_get (), image);
6064 #endif /* DISABLE_REFLECTION_EMIT */
6067 * We need to return always the same object for MethodInfo, FieldInfo etc..
6068 * but we need to consider the reflected type.
6069 * type uses a different hash, since it uses custom hash/equal functions.
6074 MonoClass *refclass;
6078 reflected_equal (gconstpointer a, gconstpointer b) {
6079 const ReflectedEntry *ea = a;
6080 const ReflectedEntry *eb = b;
6082 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6086 reflected_hash (gconstpointer a) {
6087 const ReflectedEntry *ea = a;
6088 return mono_aligned_addr_hash (ea->item);
6091 #define CHECK_OBJECT(t,p,k) \
6097 mono_domain_lock (domain); \
6098 if (!domain->refobject_hash) \
6099 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6100 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6101 mono_domain_unlock (domain); \
6104 mono_domain_unlock (domain); \
6107 #ifdef HAVE_BOEHM_GC
6108 /* ReflectedEntry doesn't need to be GC tracked */
6109 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6110 #define FREE_REFENTRY(entry) g_free ((entry))
6111 #define REFENTRY_REQUIRES_CLEANUP
6113 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6115 #define FREE_REFENTRY(entry)
6118 #define CACHE_OBJECT(t,p,o,k) \
6121 ReflectedEntry pe; \
6123 pe.refclass = (k); \
6124 mono_domain_lock (domain); \
6125 if (!domain->refobject_hash) \
6126 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6127 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6129 ReflectedEntry *e = ALLOC_REFENTRY; \
6131 e->refclass = (k); \
6132 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6135 mono_domain_unlock (domain); \
6140 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6142 mono_domain_lock (domain);
6143 if (domain->refobject_hash) {
6145 gpointer orig_pe, orig_value;
6148 pe.refclass = klass;
6149 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6150 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6151 FREE_REFENTRY (orig_pe);
6154 mono_domain_unlock (domain);
6157 #ifdef REFENTRY_REQUIRES_CLEANUP
6159 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6161 FREE_REFENTRY (key);
6166 mono_reflection_cleanup_domain (MonoDomain *domain)
6168 if (domain->refobject_hash) {
6169 /*let's avoid scanning the whole hashtable if not needed*/
6170 #ifdef REFENTRY_REQUIRES_CLEANUP
6171 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6173 mono_g_hash_table_destroy (domain->refobject_hash);
6174 domain->refobject_hash = NULL;
6178 #ifndef DISABLE_REFLECTION_EMIT
6180 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6182 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6186 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6188 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6192 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6194 MonoDynamicImage *image = moduleb->dynamic_image;
6195 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6199 MonoImage **new_modules;
6201 char *name, *fqname;
6203 * FIXME: we already created an image in mono_image_basic_init (), but
6204 * we don't know which module it belongs to, since that is only
6205 * determined at assembly save time.
6207 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6208 name = mono_string_to_utf8 (ab->name);
6209 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6210 if (!mono_error_ok (&error)) {
6212 mono_error_raise_exception (&error);
6214 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6216 moduleb->module.image = &image->image;
6217 moduleb->dynamic_image = image;
6218 register_module (mono_object_domain (moduleb), moduleb, image);
6220 /* register the module with the assembly */
6221 ass = ab->dynamic_assembly->assembly.image;
6222 module_count = ass->module_count;
6223 new_modules = g_new0 (MonoImage *, module_count + 1);
6226 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6227 new_modules [module_count] = &image->image;
6228 mono_image_addref (&image->image);
6230 g_free (ass->modules);
6231 ass->modules = new_modules;
6232 ass->module_count ++;
6237 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6239 MonoDynamicImage *image = moduleb->dynamic_image;
6241 g_assert (type->type);
6242 image->wrappers_type = mono_class_from_mono_type (type->type);
6248 * mono_assembly_get_object:
6249 * @domain: an app domain
6250 * @assembly: an assembly
6252 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6254 MonoReflectionAssembly*
6255 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6257 static MonoClass *assembly_type;
6258 MonoReflectionAssembly *res;
6260 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6261 if (!assembly_type) {
6262 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6264 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6266 assembly_type = class;
6268 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6269 res->assembly = assembly;
6271 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6276 MonoReflectionModule*
6277 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6279 static MonoClass *module_type;
6280 MonoReflectionModule *res;
6283 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6285 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6287 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6289 module_type = class;
6291 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6294 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6296 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6297 basename = g_path_get_basename (image->name);
6298 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6299 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6303 if (image->assembly->image == image) {
6304 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6308 if (image->assembly->image->modules) {
6309 for (i = 0; i < image->assembly->image->module_count; i++) {
6310 if (image->assembly->image->modules [i] == image)
6311 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6313 g_assert (res->token);
6317 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6320 MonoReflectionModule*
6321 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6323 static MonoClass *module_type;
6324 MonoReflectionModule *res;
6325 MonoTableInfo *table;
6326 guint32 cols [MONO_FILE_SIZE];
6328 guint32 i, name_idx;
6332 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6334 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6336 module_type = class;
6338 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6340 table = &image->tables [MONO_TABLE_FILE];
6341 g_assert (table_index < table->rows);
6342 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6345 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6346 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6348 /* Check whenever the row has a corresponding row in the moduleref table */
6349 table = &image->tables [MONO_TABLE_MODULEREF];
6350 for (i = 0; i < table->rows; ++i) {
6351 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6352 val = mono_metadata_string_heap (image, name_idx);
6353 if (strcmp (val, name) == 0)
6354 res->image = image->modules [i];
6357 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6358 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6359 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6360 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6361 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6367 verify_safe_for_managed_space (MonoType *type)
6369 switch (type->type) {
6371 case MONO_TYPE_ARRAY:
6372 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6374 return verify_safe_for_managed_space (type->data.type);
6375 case MONO_TYPE_SZARRAY:
6376 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6377 case MONO_TYPE_GENERICINST: {
6378 MonoGenericInst *inst = type->data.generic_class->inst;
6382 for (i = 0; i < inst->type_argc; ++i)
6383 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6389 case MONO_TYPE_MVAR:
6396 mono_type_normalize (MonoType *type)
6399 MonoGenericClass *gclass;
6400 MonoGenericInst *ginst;
6402 MonoGenericContainer *gcontainer;
6403 MonoType **argv = NULL;
6404 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6406 if (type->type != MONO_TYPE_GENERICINST)
6409 gclass = type->data.generic_class;
6410 ginst = gclass->context.class_inst;
6411 if (!ginst->is_open)
6414 gtd = gclass->container_class;
6415 gcontainer = gtd->generic_container;
6416 argv = g_newa (MonoType*, ginst->type_argc);
6418 for (i = 0; i < ginst->type_argc; ++i) {
6419 MonoType *t = ginst->type_argv [i], *norm;
6420 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6421 is_denorm_gtd = FALSE;
6422 norm = mono_type_normalize (t);
6425 requires_rebind = TRUE;
6429 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6431 if (requires_rebind) {
6432 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6433 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6439 * mono_type_get_object:
6440 * @domain: an app domain
6443 * Return an System.MonoType object representing the type @type.
6446 mono_type_get_object (MonoDomain *domain, MonoType *type)
6448 MonoType *norm_type;
6449 MonoReflectionType *res;
6450 MonoClass *klass = mono_class_from_mono_type (type);
6452 /*we must avoid using @type as it might have come
6453 * from a mono_metadata_type_dup and the caller
6454 * expects that is can be freed.
6455 * Using the right type from
6457 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6459 /* void is very common */
6460 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6461 return (MonoReflectionType*)domain->typeof_void;
6464 * If the vtable of the given class was already created, we can use
6465 * the MonoType from there and avoid all locking and hash table lookups.
6467 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6468 * that the resulting object is different.
6470 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6471 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6472 if (vtable && vtable->type)
6473 return vtable->type;
6476 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6477 mono_domain_lock (domain);
6478 if (!domain->type_hash)
6479 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6480 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6481 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6482 mono_domain_unlock (domain);
6483 mono_loader_unlock ();
6487 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6488 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6489 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6490 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6491 * artifact of how generics are encoded and should be transparent to managed code so we
6492 * need to weed out this diference when retrieving managed System.Type objects.
6494 norm_type = mono_type_normalize (type);
6495 if (norm_type != type) {
6496 res = mono_type_get_object (domain, norm_type);
6497 mono_g_hash_table_insert (domain->type_hash, type, res);
6498 mono_domain_unlock (domain);
6499 mono_loader_unlock ();
6503 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6504 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6507 if (!verify_safe_for_managed_space (type)) {
6508 mono_domain_unlock (domain);
6509 mono_loader_unlock ();
6510 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6513 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6514 gboolean is_type_done = TRUE;
6515 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6516 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6517 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6519 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6520 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6522 if (gparam->owner && gparam->owner->is_method) {
6523 MonoMethod *method = gparam->owner->owner.method;
6524 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6525 is_type_done = FALSE;
6526 } else if (gparam->owner && !gparam->owner->is_method) {
6527 MonoClass *klass = gparam->owner->owner.klass;
6528 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6529 is_type_done = FALSE;
6533 /* g_assert_not_reached (); */
6534 /* should this be considered an error condition? */
6535 if (is_type_done && !type->byref) {
6536 mono_domain_unlock (domain);
6537 mono_loader_unlock ();
6538 return mono_class_get_ref_info (klass);
6541 /* This is stored in vtables/JITted code so it has to be pinned */
6542 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6544 mono_g_hash_table_insert (domain->type_hash, type, res);
6546 if (type->type == MONO_TYPE_VOID)
6547 domain->typeof_void = (MonoObject*)res;
6549 mono_domain_unlock (domain);
6550 mono_loader_unlock ();
6555 * mono_method_get_object:
6556 * @domain: an app domain
6558 * @refclass: the reflected type (can be NULL)
6560 * Return an System.Reflection.MonoMethod object representing the method @method.
6562 MonoReflectionMethod*
6563 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6566 * We use the same C representation for methods and constructors, but the type
6567 * name in C# is different.
6569 static MonoClass *System_Reflection_MonoMethod = NULL;
6570 static MonoClass *System_Reflection_MonoCMethod = NULL;
6571 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6572 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6574 MonoReflectionMethod *ret;
6576 if (method->is_inflated) {
6577 MonoReflectionGenericMethod *gret;
6579 refclass = method->klass;
6580 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6581 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6582 if (!System_Reflection_MonoGenericCMethod)
6583 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6584 klass = System_Reflection_MonoGenericCMethod;
6586 if (!System_Reflection_MonoGenericMethod)
6587 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6588 klass = System_Reflection_MonoGenericMethod;
6590 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6591 gret->method.method = method;
6592 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6593 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6594 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6598 refclass = method->klass;
6600 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6601 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6602 if (!System_Reflection_MonoCMethod)
6603 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6604 klass = System_Reflection_MonoCMethod;
6607 if (!System_Reflection_MonoMethod)
6608 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6609 klass = System_Reflection_MonoMethod;
6611 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6612 ret->method = method;
6613 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6614 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6618 * mono_method_clear_object:
6620 * Clear the cached reflection objects for the dynamic method METHOD.
6623 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6626 g_assert (method_is_dynamic (method));
6628 klass = method->klass;
6630 clear_cached_object (domain, method, klass);
6631 klass = klass->parent;
6633 /* Added by mono_param_get_objects () */
6634 clear_cached_object (domain, &(method->signature), NULL);
6635 klass = method->klass;
6637 clear_cached_object (domain, &(method->signature), klass);
6638 klass = klass->parent;
6643 * mono_field_get_object:
6644 * @domain: an app domain
6648 * Return an System.Reflection.MonoField object representing the field @field
6651 MonoReflectionField*
6652 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6654 MonoReflectionField *res;
6655 static MonoClass *monofield_klass;
6657 CHECK_OBJECT (MonoReflectionField *, field, klass);
6658 if (!monofield_klass)
6659 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6660 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6663 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6665 if (is_field_on_inst (field)) {
6666 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6667 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6670 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6671 res->attrs = mono_field_get_flags (field);
6673 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6677 * mono_property_get_object:
6678 * @domain: an app domain
6680 * @property: a property
6682 * Return an System.Reflection.MonoProperty object representing the property @property
6685 MonoReflectionProperty*
6686 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6688 MonoReflectionProperty *res;
6689 static MonoClass *monoproperty_klass;
6691 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6692 if (!monoproperty_klass)
6693 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6694 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6696 res->property = property;
6697 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6701 * mono_event_get_object:
6702 * @domain: an app domain
6706 * Return an System.Reflection.MonoEvent object representing the event @event
6709 MonoReflectionEvent*
6710 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6712 MonoReflectionEvent *res;
6713 MonoReflectionMonoEvent *mono_event;
6714 static MonoClass *monoevent_klass;
6716 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6717 if (!monoevent_klass)
6718 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6719 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6720 mono_event->klass = klass;
6721 mono_event->event = event;
6722 res = (MonoReflectionEvent*)mono_event;
6723 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6727 * mono_get_reflection_missing_object:
6728 * @domain: Domain where the object lives
6730 * Returns the System.Reflection.Missing.Value singleton object
6731 * (of type System.Reflection.Missing).
6733 * Used as the value for ParameterInfo.DefaultValue when Optional
6737 mono_get_reflection_missing_object (MonoDomain *domain)
6740 static MonoClassField *missing_value_field = NULL;
6742 if (!missing_value_field) {
6743 MonoClass *missing_klass;
6744 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6745 mono_class_init (missing_klass);
6746 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6747 g_assert (missing_value_field);
6749 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6755 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6758 *dbnull = mono_get_dbnull_object (domain);
6763 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6765 if (!*reflection_missing)
6766 *reflection_missing = mono_get_reflection_missing_object (domain);
6767 return *reflection_missing;
6771 * mono_param_get_objects:
6772 * @domain: an app domain
6775 * Return an System.Reflection.ParameterInfo array object representing the parameters
6776 * in the method @method.
6779 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6781 static MonoClass *System_Reflection_ParameterInfo;
6782 static MonoClass *System_Reflection_ParameterInfo_array;
6784 MonoArray *res = NULL;
6785 MonoReflectionMethod *member = NULL;
6786 MonoReflectionParameter *param = NULL;
6787 char **names, **blobs = NULL;
6788 guint32 *types = NULL;
6789 MonoType *type = NULL;
6790 MonoObject *dbnull = NULL;
6791 MonoObject *missing = NULL;
6792 MonoMarshalSpec **mspecs;
6793 MonoMethodSignature *sig;
6794 MonoVTable *pinfo_vtable;
6797 if (!System_Reflection_ParameterInfo_array) {
6800 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6802 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6804 mono_memory_barrier ();
6805 System_Reflection_ParameterInfo = klass;
6808 klass = mono_array_class_get (klass, 1);
6809 mono_memory_barrier ();
6810 System_Reflection_ParameterInfo_array = klass;
6813 sig = mono_method_signature_checked (method, &error);
6814 if (!mono_error_ok (&error))
6815 mono_error_raise_exception (&error);
6817 if (!sig->param_count)
6818 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6820 /* Note: the cache is based on the address of the signature into the method
6821 * since we already cache MethodInfos with the method as keys.
6823 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6825 member = mono_method_get_object (domain, method, refclass);
6826 names = g_new (char *, sig->param_count);
6827 mono_method_get_param_names (method, (const char **) names);
6829 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6830 mono_method_get_marshal_info (method, mspecs);
6832 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6833 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6834 for (i = 0; i < sig->param_count; ++i) {
6835 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6836 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6837 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6838 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6839 param->PositionImpl = i;
6840 param->AttrsImpl = sig->params [i]->attrs;
6842 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6843 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6844 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6846 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6850 blobs = g_new0 (char *, sig->param_count);
6851 types = g_new0 (guint32, sig->param_count);
6852 get_default_param_value_blobs (method, blobs, types);
6855 /* Build MonoType for the type from the Constant Table */
6857 type = g_new0 (MonoType, 1);
6858 type->type = types [i];
6859 type->data.klass = NULL;
6860 if (types [i] == MONO_TYPE_CLASS)
6861 type->data.klass = mono_defaults.object_class;
6862 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6863 /* For enums, types [i] contains the base type */
6865 type->type = MONO_TYPE_VALUETYPE;
6866 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6868 type->data.klass = mono_class_from_mono_type (type);
6870 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6872 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6873 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6874 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6875 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6877 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6883 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6885 mono_array_setref (res, i, param);
6892 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6894 mono_metadata_free_marshal_spec (mspecs [i]);
6897 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6901 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6903 return mono_param_get_objects_internal (domain, method, NULL);
6907 * mono_method_body_get_object:
6908 * @domain: an app domain
6911 * Return an System.Reflection.MethodBody object representing the method @method.
6913 MonoReflectionMethodBody*
6914 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6916 static MonoClass *System_Reflection_MethodBody = NULL;
6917 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6918 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6919 MonoReflectionMethodBody *ret;
6920 MonoMethodHeader *header;
6922 guint32 method_rva, local_var_sig_token;
6924 unsigned char format, flags;
6927 /* for compatibility with .net */
6928 if (method_is_dynamic (method))
6929 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6931 if (!System_Reflection_MethodBody)
6932 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6933 if (!System_Reflection_LocalVariableInfo)
6934 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6935 if (!System_Reflection_ExceptionHandlingClause)
6936 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6938 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6940 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6941 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6942 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6943 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6946 image = method->klass->image;
6947 header = mono_method_get_header (method);
6949 if (!image_is_dynamic (image)) {
6950 /* Obtain local vars signature token */
6951 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6952 ptr = mono_image_rva_map (image, method_rva);
6953 flags = *(const unsigned char *) ptr;
6954 format = flags & METHOD_HEADER_FORMAT_MASK;
6956 case METHOD_HEADER_TINY_FORMAT:
6957 local_var_sig_token = 0;
6959 case METHOD_HEADER_FAT_FORMAT:
6963 local_var_sig_token = read32 (ptr);
6966 g_assert_not_reached ();
6969 local_var_sig_token = 0; //FIXME
6971 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6973 ret->init_locals = header->init_locals;
6974 ret->max_stack = header->max_stack;
6975 ret->local_var_sig_token = local_var_sig_token;
6976 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6977 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6980 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6981 for (i = 0; i < header->num_locals; ++i) {
6982 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6983 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6984 info->is_pinned = header->locals [i]->pinned;
6985 info->local_index = i;
6986 mono_array_setref (ret->locals, i, info);
6990 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6991 for (i = 0; i < header->num_clauses; ++i) {
6992 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6993 MonoExceptionClause *clause = &header->clauses [i];
6995 info->flags = clause->flags;
6996 info->try_offset = clause->try_offset;
6997 info->try_length = clause->try_len;
6998 info->handler_offset = clause->handler_offset;
6999 info->handler_length = clause->handler_len;
7000 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7001 info->filter_offset = clause->data.filter_offset;
7002 else if (clause->data.catch_class)
7003 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7005 mono_array_setref (ret->clauses, i, info);
7008 mono_metadata_free_mh (header);
7009 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7014 * mono_get_dbnull_object:
7015 * @domain: Domain where the object lives
7017 * Returns the System.DBNull.Value singleton object
7019 * Used as the value for ParameterInfo.DefaultValue
7022 mono_get_dbnull_object (MonoDomain *domain)
7025 static MonoClassField *dbnull_value_field = NULL;
7027 if (!dbnull_value_field) {
7028 MonoClass *dbnull_klass;
7029 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7030 mono_class_init (dbnull_klass);
7031 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7032 g_assert (dbnull_value_field);
7034 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7040 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7042 guint32 param_index, i, lastp, crow = 0;
7043 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7046 MonoClass *klass = method->klass;
7047 MonoImage *image = klass->image;
7048 MonoMethodSignature *methodsig = mono_method_signature (method);
7050 MonoTableInfo *constt;
7051 MonoTableInfo *methodt;
7052 MonoTableInfo *paramt;
7054 if (!methodsig->param_count)
7057 mono_class_init (klass);
7059 if (image_is_dynamic (klass->image)) {
7060 MonoReflectionMethodAux *aux;
7061 if (method->is_inflated)
7062 method = ((MonoMethodInflated*)method)->declaring;
7063 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7064 if (aux && aux->param_defaults) {
7065 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7066 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7071 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7072 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7073 constt = &image->tables [MONO_TABLE_CONSTANT];
7075 idx = mono_method_get_index (method) - 1;
7076 g_assert (idx != -1);
7078 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7079 if (idx + 1 < methodt->rows)
7080 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7082 lastp = paramt->rows + 1;
7084 for (i = param_index; i < lastp; ++i) {
7087 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7088 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7090 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7093 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7098 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7099 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7100 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7107 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7112 MonoType *basetype = type;
7117 klass = mono_class_from_mono_type (type);
7118 if (klass->valuetype) {
7119 object = mono_object_new (domain, klass);
7120 retval = ((gchar *) object + sizeof (MonoObject));
7121 if (klass->enumtype)
7122 basetype = mono_class_enum_basetype (klass);
7127 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7134 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7137 gboolean quoted = FALSE;
7139 memset (assembly, 0, sizeof (MonoAssemblyName));
7140 assembly->culture = "";
7141 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7148 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7159 /* Remove trailing whitespace */
7161 while (*s && g_ascii_isspace (*s))
7164 while (g_ascii_isspace (*p))
7167 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7169 assembly->major = strtoul (p, &s, 10);
7170 if (s == p || *s != '.')
7173 assembly->minor = strtoul (p, &s, 10);
7174 if (s == p || *s != '.')
7177 assembly->build = strtoul (p, &s, 10);
7178 if (s == p || *s != '.')
7181 assembly->revision = strtoul (p, &s, 10);
7185 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7187 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7188 assembly->culture = "";
7191 assembly->culture = p;
7192 while (*p && *p != ',') {
7196 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7198 if (strncmp (p, "null", 4) == 0) {
7203 while (*p && *p != ',') {
7206 len = (p - start + 1);
7207 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7208 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7209 g_strlcpy ((char*)assembly->public_key_token, start, len);
7212 while (*p && *p != ',')
7216 while (g_ascii_isspace (*p) || *p == ',') {
7230 * mono_reflection_parse_type:
7233 * Parse a type name as accepted by the GetType () method and output the info
7234 * extracted in the info structure.
7235 * the name param will be mangled, so, make a copy before passing it to this function.
7236 * The fields in info will be valid until the memory pointed to by name is valid.
7238 * See also mono_type_get_name () below.
7240 * Returns: 0 on parse error.
7243 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7244 MonoTypeNameParse *info)
7246 char *start, *p, *w, *last_point, *startn;
7247 int in_modifiers = 0;
7248 int isbyref = 0, rank = 0;
7250 start = p = w = name;
7252 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7253 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7254 info->name = info->name_space = NULL;
7255 info->nested = NULL;
7256 info->modifiers = NULL;
7257 info->type_arguments = NULL;
7259 /* last_point separates the namespace from the name */
7262 while (*p == ' ') p++, start++, w++, name++;
7267 *p = 0; /* NULL terminate the name */
7269 info->nested = g_list_append (info->nested, startn);
7270 /* we have parsed the nesting namespace + name */
7274 info->name_space = start;
7276 info->name = last_point + 1;
7278 info->name_space = (char *)"";
7306 info->name_space = start;
7308 info->name = last_point + 1;
7310 info->name_space = (char *)"";
7317 if (isbyref) /* only one level allowed by the spec */
7320 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7324 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7328 //Decide if it's an array of a generic argument list
7333 if (*p == ',' || *p == '*' || *p == ']') { //array
7340 else if (*p == '*') /* '*' means unknown lower bound */
7341 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7348 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7350 if (rank) /* generic args after array spec*/ //XXX test
7352 info->type_arguments = g_ptr_array_new ();
7354 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7355 gboolean fqname = FALSE;
7357 g_ptr_array_add (info->type_arguments, subinfo);
7364 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7367 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7368 if (fqname && (*p != ']')) {
7376 while (*p && (*p != ']'))
7384 if (g_ascii_isspace (*aname)) {
7391 !assembly_name_to_aname (&subinfo->assembly, aname))
7393 } else if (fqname && (*p == ']')) {
7415 if (g_ascii_isspace (*p)) {
7422 return 0; /* missing assembly name */
7423 if (!assembly_name_to_aname (&info->assembly, p))
7429 if (info->assembly.name)
7432 // *w = 0; /* terminate class name */
7434 if (!info->name || !*info->name)
7438 /* add other consistency checks */
7443 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7445 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7449 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7451 gboolean type_resolve = FALSE;
7453 MonoImage *rootimage = image;
7455 if (info->assembly.name) {
7456 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7457 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7459 * This could happen in the AOT compiler case when the search hook is not
7462 assembly = image->assembly;
7464 /* then we must load the assembly ourselve - see #60439 */
7465 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7469 image = assembly->image;
7470 } else if (!image) {
7471 image = mono_defaults.corlib;
7474 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7475 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7476 image = mono_defaults.corlib;
7477 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7484 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7489 gboolean bounded = FALSE;
7492 image = mono_defaults.corlib;
7496 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7497 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7499 klass = mono_class_from_name (image, info->name_space, info->name);
7503 for (mod = info->nested; mod; mod = mod->next) {
7504 gpointer iter = NULL;
7508 mono_class_init (parent);
7510 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7512 char *nested_name, *nested_nspace;
7513 gboolean match = TRUE;
7515 lastp = strrchr (mod->data, '.');
7517 /* Nested classes can have namespaces */
7520 nested_name = g_strdup (lastp + 1);
7521 nspace_len = lastp - (char*)mod->data;
7522 nested_nspace = g_malloc (nspace_len + 1);
7523 memcpy (nested_nspace, mod->data, nspace_len);
7524 nested_nspace [nspace_len] = '\0';
7527 nested_name = mod->data;
7528 nested_nspace = NULL;
7531 if (nested_nspace) {
7533 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7536 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7542 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7545 if (strcmp (klass->name, nested_name) != 0)
7550 g_free (nested_name);
7551 g_free (nested_nspace);
7563 if (info->type_arguments) {
7564 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7565 MonoReflectionType *the_type;
7569 for (i = 0; i < info->type_arguments->len; i++) {
7570 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7572 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7573 if (!type_args [i]) {
7579 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7581 instance = mono_reflection_bind_generic_parameters (
7582 the_type, info->type_arguments->len, type_args);
7588 klass = mono_class_from_mono_type (instance);
7591 for (mod = info->modifiers; mod; mod = mod->next) {
7592 modval = GPOINTER_TO_UINT (mod->data);
7593 if (!modval) { /* byref: must be last modifier */
7594 return &klass->this_arg;
7595 } else if (modval == -1) {
7596 klass = mono_ptr_class_get (&klass->byval_arg);
7597 } else if (modval == -2) {
7599 } else { /* array rank */
7600 klass = mono_bounded_array_class_get (klass, modval, bounded);
7604 return &klass->byval_arg;
7608 * mono_reflection_get_type:
7609 * @image: a metadata context
7610 * @info: type description structure
7611 * @ignorecase: flag for case-insensitive string compares
7612 * @type_resolve: whenever type resolve was already tried
7614 * Build a MonoType from the type description in @info.
7619 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7620 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7624 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7626 MonoReflectionAssemblyBuilder *abuilder;
7630 g_assert (assembly_is_dynamic (assembly));
7631 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7633 /* Enumerate all modules */
7636 if (abuilder->modules) {
7637 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7638 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7639 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7645 if (!type && abuilder->loaded_modules) {
7646 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7647 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7648 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7658 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7661 MonoReflectionAssembly *assembly;
7665 if (image && image_is_dynamic (image))
7666 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7668 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7671 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7678 *type_resolve = TRUE;
7681 /* Reconstruct the type name */
7682 fullName = g_string_new ("");
7683 if (info->name_space && (info->name_space [0] != '\0'))
7684 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7686 g_string_printf (fullName, "%s", info->name);
7687 for (mod = info->nested; mod; mod = mod->next)
7688 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7690 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7692 if (assembly_is_dynamic (assembly->assembly))
7693 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7695 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7698 g_string_free (fullName, TRUE);
7703 mono_reflection_free_type_info (MonoTypeNameParse *info)
7705 g_list_free (info->modifiers);
7706 g_list_free (info->nested);
7708 if (info->type_arguments) {
7711 for (i = 0; i < info->type_arguments->len; i++) {
7712 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7714 mono_reflection_free_type_info (subinfo);
7715 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7719 g_ptr_array_free (info->type_arguments, TRUE);
7724 * mono_reflection_type_from_name:
7726 * @image: a metadata context (can be NULL).
7728 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7729 * it defaults to get the type from @image or, if @image is NULL or loading
7730 * from it fails, uses corlib.
7734 mono_reflection_type_from_name (char *name, MonoImage *image)
7736 MonoType *type = NULL;
7737 MonoTypeNameParse info;
7740 /* Make a copy since parse_type modifies its argument */
7741 tmp = g_strdup (name);
7743 /*g_print ("requested type %s\n", str);*/
7744 if (mono_reflection_parse_type (tmp, &info)) {
7745 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7749 mono_reflection_free_type_info (&info);
7754 * mono_reflection_get_token:
7756 * Return the metadata token of OBJ which should be an object
7757 * representing a metadata element.
7760 mono_reflection_get_token (MonoObject *obj)
7765 klass = obj->vtable->klass;
7767 if (strcmp (klass->name, "MethodBuilder") == 0) {
7768 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7770 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7771 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7772 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7774 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7775 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7776 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7778 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7779 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7780 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7781 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7782 } else if (strcmp (klass->name, "MonoType") == 0) {
7783 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7784 MonoClass *mc = mono_class_from_mono_type (type);
7785 if (!mono_class_init (mc))
7786 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7788 token = mc->type_token;
7789 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7790 strcmp (klass->name, "MonoMethod") == 0 ||
7791 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7792 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7793 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7794 if (m->method->is_inflated) {
7795 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7796 return inflated->declaring->token;
7798 token = m->method->token;
7800 } else if (strcmp (klass->name, "MonoField") == 0) {
7801 MonoReflectionField *f = (MonoReflectionField*)obj;
7803 if (is_field_on_inst (f->field)) {
7804 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7806 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7807 int field_index = f->field - dgclass->fields;
7810 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7811 obj = dgclass->field_objects [field_index];
7812 return mono_reflection_get_token (obj);
7815 token = mono_class_get_field_token (f->field);
7816 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7817 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7819 token = mono_class_get_property_token (p->property);
7820 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7821 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7823 token = mono_class_get_event_token (p->event);
7824 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7825 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7826 MonoClass *member_class = mono_object_class (p->MemberImpl);
7827 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7829 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7830 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7831 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7834 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7835 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7837 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7838 MonoException *ex = mono_get_exception_not_implemented (msg);
7840 mono_raise_exception (ex);
7847 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7851 int slen = mono_metadata_decode_value (p, &p);
7853 mono_error_init (error);
7855 n = g_memdup (p, slen + 1);
7857 t = mono_reflection_type_from_name (n, image);
7859 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7860 /* We don't free n, it's consumed by mono_error */
7861 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7867 return mono_class_from_mono_type (t);
7871 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7873 int slen, type = t->type;
7874 MonoClass *tklass = t->data.klass;
7876 mono_error_init (error);
7882 case MONO_TYPE_BOOLEAN: {
7883 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7888 case MONO_TYPE_CHAR:
7890 case MONO_TYPE_I2: {
7891 guint16 *val = g_malloc (sizeof (guint16));
7896 #if SIZEOF_VOID_P == 4
7902 case MONO_TYPE_I4: {
7903 guint32 *val = g_malloc (sizeof (guint32));
7908 #if SIZEOF_VOID_P == 8
7909 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7913 case MONO_TYPE_I8: {
7914 guint64 *val = g_malloc (sizeof (guint64));
7919 case MONO_TYPE_R8: {
7920 double *val = g_malloc (sizeof (double));
7925 case MONO_TYPE_VALUETYPE:
7926 if (t->data.klass->enumtype) {
7927 type = mono_class_enum_basetype (t->data.klass)->type;
7930 MonoClass *k = t->data.klass;
7932 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7933 guint64 *val = g_malloc (sizeof (guint64));
7939 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7942 case MONO_TYPE_STRING:
7943 if (*p == (char)0xFF) {
7947 slen = mono_metadata_decode_value (p, &p);
7949 return mono_string_new_len (mono_domain_get (), p, slen);
7950 case MONO_TYPE_CLASS: {
7953 if (*p == (char)0xFF) {
7958 slen = mono_metadata_decode_value (p, &p);
7959 n = g_memdup (p, slen + 1);
7961 t = mono_reflection_type_from_name (n, image);
7963 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7964 /* We don't free n, it's consumed by mono_error */
7965 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7970 return mono_type_get_object (mono_domain_get (), t);
7972 case MONO_TYPE_OBJECT: {
7975 MonoClass *subc = NULL;
7980 } else if (subt == 0x0E) {
7981 type = MONO_TYPE_STRING;
7983 } else if (subt == 0x1D) {
7984 MonoType simple_type = {{0}};
7988 type = MONO_TYPE_SZARRAY;
7989 if (etype == 0x50) {
7990 tklass = mono_defaults.systemtype_class;
7991 } else if (etype == 0x55) {
7992 tklass = load_cattr_enum_type (image, p, &p, error);
7993 if (!mono_error_ok (error))
7997 /* See Partition II, Appendix B3 */
7998 etype = MONO_TYPE_OBJECT;
7999 simple_type.type = etype;
8000 tklass = mono_class_from_mono_type (&simple_type);
8003 } else if (subt == 0x55) {
8006 slen = mono_metadata_decode_value (p, &p);
8007 n = g_memdup (p, slen + 1);
8009 t = mono_reflection_type_from_name (n, image);
8011 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8012 /* We don't free n, it's consumed by mono_error */
8013 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8018 subc = mono_class_from_mono_type (t);
8019 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8020 MonoType simple_type = {{0}};
8021 simple_type.type = subt;
8022 subc = mono_class_from_mono_type (&simple_type);
8024 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8026 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8028 if (mono_error_ok (error)) {
8029 obj = mono_object_new (mono_domain_get (), subc);
8030 g_assert (!subc->has_references);
8031 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8037 case MONO_TYPE_SZARRAY: {
8039 guint32 i, alen, basetype;
8042 if (alen == 0xffffffff) {
8046 arr = mono_array_new (mono_domain_get(), tklass, alen);
8047 basetype = tklass->byval_arg.type;
8048 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8049 basetype = mono_class_enum_basetype (tklass)->type;
8054 case MONO_TYPE_BOOLEAN:
8055 for (i = 0; i < alen; i++) {
8056 MonoBoolean val = *p++;
8057 mono_array_set (arr, MonoBoolean, i, val);
8060 case MONO_TYPE_CHAR:
8063 for (i = 0; i < alen; i++) {
8064 guint16 val = read16 (p);
8065 mono_array_set (arr, guint16, i, val);
8072 for (i = 0; i < alen; i++) {
8073 guint32 val = read32 (p);
8074 mono_array_set (arr, guint32, i, val);
8079 for (i = 0; i < alen; i++) {
8082 mono_array_set (arr, double, i, val);
8088 for (i = 0; i < alen; i++) {
8089 guint64 val = read64 (p);
8090 mono_array_set (arr, guint64, i, val);
8094 case MONO_TYPE_CLASS:
8095 case MONO_TYPE_OBJECT:
8096 case MONO_TYPE_STRING:
8097 case MONO_TYPE_SZARRAY:
8098 for (i = 0; i < alen; i++) {
8099 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8100 if (!mono_error_ok (error))
8102 mono_array_setref (arr, i, item);
8106 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8112 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8118 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8120 static MonoClass *klass;
8121 static MonoMethod *ctor;
8123 void *params [2], *unboxed;
8126 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8128 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8130 params [0] = mono_type_get_object (mono_domain_get (), t);
8132 retval = mono_object_new (mono_domain_get (), klass);
8133 unboxed = mono_object_unbox (retval);
8134 mono_runtime_invoke (ctor, unboxed, params, NULL);
8140 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8142 static MonoClass *klass;
8143 static MonoMethod *ctor;
8145 void *unboxed, *params [2];
8148 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8150 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8153 params [1] = typedarg;
8154 retval = mono_object_new (mono_domain_get (), klass);
8155 unboxed = mono_object_unbox (retval);
8156 mono_runtime_invoke (ctor, unboxed, params, NULL);
8162 type_is_reference (MonoType *type)
8164 switch (type->type) {
8165 case MONO_TYPE_BOOLEAN:
8166 case MONO_TYPE_CHAR:
8179 case MONO_TYPE_VALUETYPE:
8187 free_param_data (MonoMethodSignature *sig, void **params) {
8189 for (i = 0; i < sig->param_count; ++i) {
8190 if (!type_is_reference (sig->params [i]))
8191 g_free (params [i]);
8196 * Find the field index in the metadata FieldDef table.
8199 find_field_index (MonoClass *klass, MonoClassField *field) {
8202 for (i = 0; i < klass->field.count; ++i) {
8203 if (field == &klass->fields [i])
8204 return klass->field.first + 1 + i;
8210 * Find the property index in the metadata Property table.
8213 find_property_index (MonoClass *klass, MonoProperty *property) {
8216 for (i = 0; i < klass->ext->property.count; ++i) {
8217 if (property == &klass->ext->properties [i])
8218 return klass->ext->property.first + 1 + i;
8224 * Find the event index in the metadata Event table.
8227 find_event_index (MonoClass *klass, MonoEvent *event) {
8230 for (i = 0; i < klass->ext->event.count; ++i) {
8231 if (event == &klass->ext->events [i])
8232 return klass->ext->event.first + 1 + i;
8238 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8240 const char *p = (const char*)data;
8242 guint32 i, j, num_named;
8244 void *params_buf [32];
8245 void **params = NULL;
8246 MonoMethodSignature *sig;
8247 MonoObject *exc = NULL;
8249 mono_error_init (error);
8251 mono_class_init (method->klass);
8253 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8254 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8259 attr = mono_object_new (mono_domain_get (), method->klass);
8260 mono_runtime_invoke (method, attr, NULL, NULL);
8264 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8267 /*g_print ("got attr %s\n", method->klass->name);*/
8269 sig = mono_method_signature (method);
8270 if (sig->param_count < 32) {
8271 params = params_buf;
8272 memset (params, 0, sizeof (void*) * sig->param_count);
8274 /* Allocate using GC so it gets GC tracking */
8275 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8280 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8281 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8282 if (!mono_error_ok (error))
8287 attr = mono_object_new (mono_domain_get (), method->klass);
8289 mono_runtime_invoke (method, attr, params, &exc);
8292 num_named = read16 (named);
8294 for (j = 0; j < num_named; j++) {
8296 char *name, named_type, data_type;
8297 named_type = *named++;
8298 data_type = *named++; /* type of data */
8299 if (data_type == MONO_TYPE_SZARRAY)
8300 data_type = *named++;
8301 if (data_type == MONO_TYPE_ENUM) {
8304 type_len = mono_metadata_decode_blob_size (named, &named);
8305 type_name = g_malloc (type_len + 1);
8306 memcpy (type_name, named, type_len);
8307 type_name [type_len] = 0;
8309 /* FIXME: lookup the type and check type consistency */
8312 name_len = mono_metadata_decode_blob_size (named, &named);
8313 name = g_malloc (name_len + 1);
8314 memcpy (name, named, name_len);
8315 name [name_len] = 0;
8317 if (named_type == 0x53) {
8318 MonoClassField *field;
8321 /* how this fail is a blackbox */
8322 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8324 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8329 val = load_cattr_value (image, field->type, named, &named, error);
8330 if (!mono_error_ok (error)) {
8332 if (!type_is_reference (field->type))
8337 mono_field_set_value (attr, field, val);
8338 if (!type_is_reference (field->type))
8340 } else if (named_type == 0x54) {
8343 MonoType *prop_type;
8345 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8348 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8354 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8359 /* can we have more that 1 arg in a custom attr named property? */
8360 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8361 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8363 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8364 if (!mono_error_ok (error)) {
8366 if (!type_is_reference (prop_type))
8367 g_free (pparams [0]);
8372 mono_property_set_value (prop, attr, pparams, NULL);
8373 if (!type_is_reference (prop_type))
8374 g_free (pparams [0]);
8379 free_param_data (method->signature, params);
8380 if (params != params_buf)
8381 mono_gc_free_fixed (params);
8386 free_param_data (method->signature, params);
8387 if (params != params_buf)
8388 mono_gc_free_fixed (params);
8390 mono_raise_exception ((MonoException*)exc);
8395 * mono_reflection_create_custom_attr_data_args:
8397 * Create an array of typed and named arguments from the cattr blob given by DATA.
8398 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8399 * NAMED_ARG_INFO will contain information about the named arguments.
8402 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)
8404 MonoArray *typedargs, *namedargs;
8405 MonoClass *attrklass;
8407 const char *p = (const char*)data;
8409 guint32 i, j, num_named;
8410 CattrNamedArg *arginfo = NULL;
8414 *named_arg_info = NULL;
8416 mono_error_init (error);
8418 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8419 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8423 mono_class_init (method->klass);
8425 domain = mono_domain_get ();
8427 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8430 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8434 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8438 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8439 if (!mono_error_ok (error)) {
8440 if (!type_is_reference (mono_method_signature (method)->params [i]))
8445 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8446 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8447 mono_array_setref (typedargs, i, obj);
8449 if (!type_is_reference (mono_method_signature (method)->params [i]))
8454 num_named = read16 (named);
8455 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8457 attrklass = method->klass;
8459 arginfo = g_new0 (CattrNamedArg, num_named);
8460 *named_arg_info = arginfo;
8462 for (j = 0; j < num_named; j++) {
8464 char *name, named_type, data_type;
8465 named_type = *named++;
8466 data_type = *named++; /* type of data */
8467 if (data_type == MONO_TYPE_SZARRAY)
8468 data_type = *named++;
8469 if (data_type == MONO_TYPE_ENUM) {
8472 type_len = mono_metadata_decode_blob_size (named, &named);
8473 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8476 type_name = g_malloc (type_len + 1);
8477 memcpy (type_name, named, type_len);
8478 type_name [type_len] = 0;
8480 /* FIXME: lookup the type and check type consistency */
8483 name_len = mono_metadata_decode_blob_size (named, &named);
8484 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8486 name = g_malloc (name_len + 1);
8487 memcpy (name, named, name_len);
8488 name [name_len] = 0;
8490 if (named_type == 0x53) {
8492 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8500 arginfo [j].type = field->type;
8501 arginfo [j].field = field;
8503 val = load_cattr_value (image, field->type, named, &named, error);
8504 if (!mono_error_ok (error)) {
8505 if (!type_is_reference (field->type))
8511 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8512 mono_array_setref (namedargs, j, obj);
8513 if (!type_is_reference (field->type))
8515 } else if (named_type == 0x54) {
8517 MonoType *prop_type;
8518 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8521 if (!prop || !prop->set) {
8526 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8527 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8529 arginfo [j].type = prop_type;
8530 arginfo [j].prop = prop;
8532 val = load_cattr_value (image, prop_type, named, &named, error);
8533 if (!mono_error_ok (error)) {
8534 if (!type_is_reference (prop_type))
8540 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8541 mono_array_setref (namedargs, j, obj);
8542 if (!type_is_reference (prop_type))
8548 *typed_args = typedargs;
8549 *named_args = namedargs;
8552 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8554 *named_arg_info = NULL;
8558 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8561 MonoArray *typedargs, *namedargs;
8564 CattrNamedArg *arginfo = NULL;
8574 image = assembly->assembly->image;
8575 method = ref_method->method;
8576 domain = mono_object_domain (ref_method);
8578 if (!mono_class_init (method->klass))
8579 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8581 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8582 if (!mono_error_ok (&error))
8583 mono_error_raise_exception (&error);
8584 if (mono_loader_get_last_error ())
8585 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8587 if (!typedargs || !namedargs) {
8592 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8593 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8594 MonoObject *typedarg;
8596 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8597 mono_array_setref (typedargs, i, typedarg);
8600 for (i = 0; i < mono_array_length (namedargs); ++i) {
8601 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8602 MonoObject *typedarg, *namedarg, *minfo;
8604 if (arginfo [i].prop)
8605 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8607 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8609 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8610 namedarg = create_cattr_named_arg (minfo, typedarg);
8612 mono_array_setref (namedargs, i, namedarg);
8615 *ctor_args = typedargs;
8616 *named_args = namedargs;
8621 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8623 static MonoMethod *ctor;
8628 g_assert (image->assembly);
8631 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8633 domain = mono_domain_get ();
8634 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8635 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8636 params [1] = mono_assembly_get_object (domain, image->assembly);
8637 params [2] = (gpointer)&cattr->data;
8638 params [3] = &cattr->data_size;
8639 mono_runtime_invoke (ctor, attr, params, NULL);
8644 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8650 mono_error_init (error);
8653 for (i = 0; i < cinfo->num_attrs; ++i) {
8654 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8658 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8660 for (i = 0; i < cinfo->num_attrs; ++i) {
8661 if (!cinfo->attrs [i].ctor)
8662 /* The cattr type is not finished yet */
8663 /* We should include the type name but cinfo doesn't contain it */
8664 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8665 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8666 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8667 if (!mono_error_ok (error))
8669 mono_array_setref (result, n, attr);
8677 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8680 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8681 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8687 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8693 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8694 for (i = 0; i < cinfo->num_attrs; ++i) {
8695 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8696 mono_array_setref (result, i, attr);
8702 * mono_custom_attrs_from_index:
8704 * Returns: NULL if no attributes are found or if a loading error occurs.
8707 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8709 guint32 mtoken, i, len;
8710 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8712 MonoCustomAttrInfo *ainfo;
8713 GList *tmp, *list = NULL;
8716 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8718 i = mono_metadata_custom_attrs_from_index (image, idx);
8722 while (i < ca->rows) {
8723 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8725 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8728 len = g_list_length (list);
8731 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8732 ainfo->num_attrs = len;
8733 ainfo->image = image;
8734 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8735 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8736 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8737 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8738 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8739 mtoken |= MONO_TOKEN_METHOD_DEF;
8741 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8742 mtoken |= MONO_TOKEN_MEMBER_REF;
8745 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8748 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8749 if (!ainfo->attrs [i].ctor) {
8750 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8756 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8757 /*FIXME raising an exception here doesn't make any sense*/
8758 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8763 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8764 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8765 ainfo->attrs [i].data = (guchar*)data;
8773 mono_custom_attrs_from_method (MonoMethod *method)
8778 * An instantiated method has the same cattrs as the generic method definition.
8780 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8781 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8783 if (method->is_inflated)
8784 method = ((MonoMethodInflated *) method)->declaring;
8786 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8787 return lookup_custom_attr (method->klass->image, method);
8790 /* Synthetic methods */
8793 idx = mono_method_get_index (method);
8794 idx <<= MONO_CUSTOM_ATTR_BITS;
8795 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8796 return mono_custom_attrs_from_index (method->klass->image, idx);
8800 mono_custom_attrs_from_class (MonoClass *klass)
8804 if (klass->generic_class)
8805 klass = klass->generic_class->container_class;
8807 if (image_is_dynamic (klass->image))
8808 return lookup_custom_attr (klass->image, klass);
8810 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8811 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8812 idx <<= MONO_CUSTOM_ATTR_BITS;
8813 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8815 idx = mono_metadata_token_index (klass->type_token);
8816 idx <<= MONO_CUSTOM_ATTR_BITS;
8817 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8819 return mono_custom_attrs_from_index (klass->image, idx);
8823 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8827 if (image_is_dynamic (assembly->image))
8828 return lookup_custom_attr (assembly->image, assembly);
8829 idx = 1; /* there is only one assembly */
8830 idx <<= MONO_CUSTOM_ATTR_BITS;
8831 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8832 return mono_custom_attrs_from_index (assembly->image, idx);
8835 static MonoCustomAttrInfo*
8836 mono_custom_attrs_from_module (MonoImage *image)
8840 if (image_is_dynamic (image))
8841 return lookup_custom_attr (image, image);
8842 idx = 1; /* there is only one module */
8843 idx <<= MONO_CUSTOM_ATTR_BITS;
8844 idx |= MONO_CUSTOM_ATTR_MODULE;
8845 return mono_custom_attrs_from_index (image, idx);
8849 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8853 if (image_is_dynamic (klass->image)) {
8854 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8855 return lookup_custom_attr (klass->image, property);
8857 idx = find_property_index (klass, property);
8858 idx <<= MONO_CUSTOM_ATTR_BITS;
8859 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8860 return mono_custom_attrs_from_index (klass->image, idx);
8864 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8868 if (image_is_dynamic (klass->image)) {
8869 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8870 return lookup_custom_attr (klass->image, event);
8872 idx = find_event_index (klass, event);
8873 idx <<= MONO_CUSTOM_ATTR_BITS;
8874 idx |= MONO_CUSTOM_ATTR_EVENT;
8875 return mono_custom_attrs_from_index (klass->image, idx);
8879 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8882 if (image_is_dynamic (klass->image)) {
8883 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8884 return lookup_custom_attr (klass->image, field);
8886 idx = find_field_index (klass, field);
8887 idx <<= MONO_CUSTOM_ATTR_BITS;
8888 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8889 return mono_custom_attrs_from_index (klass->image, idx);
8893 * mono_custom_attrs_from_param:
8894 * @method: handle to the method that we want to retrieve custom parameter information from
8895 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8897 * The result must be released with mono_custom_attrs_free().
8899 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8902 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8905 guint32 i, idx, method_index;
8906 guint32 param_list, param_last, param_pos, found;
8908 MonoReflectionMethodAux *aux;
8911 * An instantiated method has the same cattrs as the generic method definition.
8913 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8914 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8916 if (method->is_inflated)
8917 method = ((MonoMethodInflated *) method)->declaring;
8919 if (image_is_dynamic (method->klass->image)) {
8920 MonoCustomAttrInfo *res, *ainfo;
8923 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8924 if (!aux || !aux->param_cattr)
8927 /* Need to copy since it will be freed later */
8928 ainfo = aux->param_cattr [param];
8931 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8932 res = g_malloc0 (size);
8933 memcpy (res, ainfo, size);
8937 image = method->klass->image;
8938 method_index = mono_method_get_index (method);
8941 ca = &image->tables [MONO_TABLE_METHOD];
8943 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8944 if (method_index == ca->rows) {
8945 ca = &image->tables [MONO_TABLE_PARAM];
8946 param_last = ca->rows + 1;
8948 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8949 ca = &image->tables [MONO_TABLE_PARAM];
8952 for (i = param_list; i < param_last; ++i) {
8953 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8954 if (param_pos == param) {
8962 idx <<= MONO_CUSTOM_ATTR_BITS;
8963 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8964 return mono_custom_attrs_from_index (image, idx);
8968 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8972 for (i = 0; i < ainfo->num_attrs; ++i) {
8973 klass = ainfo->attrs [i].ctor->klass;
8974 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8981 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8984 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
8985 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8990 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
8996 mono_error_init (error);
8999 for (i = 0; i < ainfo->num_attrs; ++i) {
9000 klass = ainfo->attrs [i].ctor->klass;
9001 if (mono_class_has_parent (klass, attr_klass)) {
9006 if (attr_index == -1)
9009 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9010 if (!mono_error_ok (error))
9012 return mono_array_get (attrs, MonoObject*, attr_index);
9016 * mono_reflection_get_custom_attrs_info:
9017 * @obj: a reflection object handle
9019 * Return the custom attribute info for attributes defined for the
9020 * reflection handle @obj. The objects.
9022 * FIXME this function leaks like a sieve for SRE objects.
9025 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9028 MonoCustomAttrInfo *cinfo = NULL;
9030 klass = obj->vtable->klass;
9031 if (klass == mono_defaults.monotype_class) {
9032 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9033 klass = mono_class_from_mono_type (type);
9034 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9035 cinfo = mono_custom_attrs_from_class (klass);
9036 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9037 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9038 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9039 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9040 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9041 cinfo = mono_custom_attrs_from_module (module->image);
9042 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9043 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9044 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9045 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9046 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9047 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9048 } else if (strcmp ("MonoField", klass->name) == 0) {
9049 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9050 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9051 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9052 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9053 cinfo = mono_custom_attrs_from_method (rmethod->method);
9054 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9055 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9056 cinfo = mono_custom_attrs_from_method (rmethod->method);
9057 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9058 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9059 MonoClass *member_class = mono_object_class (param->MemberImpl);
9060 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9061 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9062 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9063 } else if (is_sr_mono_property (member_class)) {
9064 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9066 if (!(method = prop->property->get))
9067 method = prop->property->set;
9070 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9072 #ifndef DISABLE_REFLECTION_EMIT
9073 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9074 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9075 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9076 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9077 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9078 MonoMethod *method = NULL;
9079 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9080 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9081 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9082 method = ((MonoReflectionMethod *)c->cb)->method;
9084 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));
9086 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9090 char *type_name = mono_type_get_full_name (member_class);
9091 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9092 MonoException *ex = mono_get_exception_not_supported (msg);
9095 mono_raise_exception (ex);
9097 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9098 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9099 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9100 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9101 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9102 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9103 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9104 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9105 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9106 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9107 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9108 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9109 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9110 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9111 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9112 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9113 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9114 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9115 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9116 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9117 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9118 } else { /* handle other types here... */
9119 g_error ("get custom attrs not yet supported for %s", klass->name);
9126 * mono_reflection_get_custom_attrs_by_type:
9127 * @obj: a reflection object handle
9129 * Return an array with all the custom attributes defined of the
9130 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9131 * of that type are returned. The objects are fully build. Return NULL if a loading error
9135 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9138 MonoCustomAttrInfo *cinfo;
9140 mono_error_init (error);
9142 cinfo = mono_reflection_get_custom_attrs_info (obj);
9144 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9146 mono_custom_attrs_free (cinfo);
9148 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9149 if (mono_loader_get_last_error ())
9151 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9158 * mono_reflection_get_custom_attrs:
9159 * @obj: a reflection object handle
9161 * Return an array with all the custom attributes defined of the
9162 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9166 mono_reflection_get_custom_attrs (MonoObject *obj)
9170 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9174 * mono_reflection_get_custom_attrs_data:
9175 * @obj: a reflection obj handle
9177 * Returns an array of System.Reflection.CustomAttributeData,
9178 * which include information about attributes reflected on
9179 * types loaded using the Reflection Only methods
9182 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9185 MonoCustomAttrInfo *cinfo;
9187 cinfo = mono_reflection_get_custom_attrs_info (obj);
9189 result = mono_custom_attrs_data_construct (cinfo);
9191 mono_custom_attrs_free (cinfo);
9193 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9198 static MonoReflectionType*
9199 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9201 static MonoMethod *method_get_underlying_system_type = NULL;
9202 MonoMethod *usertype_method;
9204 if (!method_get_underlying_system_type)
9205 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9206 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9207 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9212 is_corlib_type (MonoClass *class)
9214 return class->image == mono_defaults.corlib;
9217 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9218 static MonoClass *cached_class; \
9220 return cached_class == _class; \
9221 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9222 cached_class = _class; \
9229 #ifndef DISABLE_REFLECTION_EMIT
9231 is_sre_array (MonoClass *class)
9233 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9237 is_sre_byref (MonoClass *class)
9239 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9243 is_sre_pointer (MonoClass *class)
9245 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9249 is_sre_generic_instance (MonoClass *class)
9251 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9255 is_sre_type_builder (MonoClass *class)
9257 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9261 is_sre_method_builder (MonoClass *class)
9263 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9267 is_sre_ctor_builder (MonoClass *class)
9269 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9273 is_sre_field_builder (MonoClass *class)
9275 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9279 is_sre_method_on_tb_inst (MonoClass *class)
9281 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9285 is_sre_ctor_on_tb_inst (MonoClass *class)
9287 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9291 mono_reflection_type_get_handle (MonoReflectionType* ref)
9299 if (is_usertype (ref)) {
9300 ref = mono_reflection_type_get_underlying_system_type (ref);
9301 if (ref == NULL || is_usertype (ref))
9307 class = mono_object_class (ref);
9309 if (is_sre_array (class)) {
9311 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9312 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9314 if (sre_array->rank == 0) //single dimentional array
9315 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9317 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9318 sre_array->type.type = res;
9320 } else if (is_sre_byref (class)) {
9322 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9323 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9325 res = &mono_class_from_mono_type (base)->this_arg;
9326 sre_byref->type.type = res;
9328 } else if (is_sre_pointer (class)) {
9330 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9331 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9333 res = &mono_ptr_class_get (base)->byval_arg;
9334 sre_pointer->type.type = res;
9336 } else if (is_sre_generic_instance (class)) {
9337 MonoType *res, **types;
9338 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9341 count = mono_array_length (gclass->type_arguments);
9342 types = g_new0 (MonoType*, count);
9343 for (i = 0; i < count; ++i) {
9344 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9345 types [i] = mono_reflection_type_get_handle (t);
9352 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9355 gclass->type.type = res;
9359 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9366 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9368 mono_reflection_type_get_handle (type);
9372 mono_reflection_register_with_runtime (MonoReflectionType *type)
9374 MonoType *res = mono_reflection_type_get_handle (type);
9375 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9379 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9381 class = mono_class_from_mono_type (res);
9383 mono_loader_lock (); /*same locking as mono_type_get_object*/
9384 mono_domain_lock (domain);
9386 if (!image_is_dynamic (class->image)) {
9387 mono_class_setup_supertypes (class);
9389 if (!domain->type_hash)
9390 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9391 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9392 mono_g_hash_table_insert (domain->type_hash, res, type);
9394 mono_domain_unlock (domain);
9395 mono_loader_unlock ();
9399 * LOCKING: Assumes the loader lock is held.
9401 static MonoMethodSignature*
9402 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9403 MonoMethodSignature *sig;
9406 count = parameters? mono_array_length (parameters): 0;
9408 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9409 sig->param_count = count;
9410 sig->sentinelpos = -1; /* FIXME */
9411 for (i = 0; i < count; ++i)
9412 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9417 * LOCKING: Assumes the loader lock is held.
9419 static MonoMethodSignature*
9420 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9421 MonoMethodSignature *sig;
9423 sig = parameters_to_signature (image, ctor->parameters);
9424 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9425 sig->ret = &mono_defaults.void_class->byval_arg;
9430 * LOCKING: Assumes the loader lock is held.
9432 static MonoMethodSignature*
9433 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9434 MonoMethodSignature *sig;
9436 sig = parameters_to_signature (image, method->parameters);
9437 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9438 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9439 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9443 static MonoMethodSignature*
9444 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9445 MonoMethodSignature *sig;
9447 sig = parameters_to_signature (NULL, method->parameters);
9448 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9449 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9450 sig->generic_param_count = 0;
9455 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9457 MonoClass *klass = mono_object_class (prop);
9458 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9459 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9460 *name = mono_string_to_utf8 (pb->name);
9461 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9463 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9464 *name = g_strdup (p->property->name);
9465 if (p->property->get)
9466 *type = mono_method_signature (p->property->get)->ret;
9468 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9473 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9475 MonoClass *klass = mono_object_class (field);
9476 if (strcmp (klass->name, "FieldBuilder") == 0) {
9477 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9478 *name = mono_string_to_utf8 (fb->name);
9479 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9481 MonoReflectionField *f = (MonoReflectionField *)field;
9482 *name = g_strdup (mono_field_get_name (f->field));
9483 *type = f->field->type;
9487 #else /* DISABLE_REFLECTION_EMIT */
9490 mono_reflection_register_with_runtime (MonoReflectionType *type)
9496 is_sre_type_builder (MonoClass *class)
9502 is_sre_generic_instance (MonoClass *class)
9508 init_type_builder_generics (MonoObject *type)
9512 #endif /* !DISABLE_REFLECTION_EMIT */
9516 is_sr_mono_field (MonoClass *class)
9518 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9522 is_sr_mono_property (MonoClass *class)
9524 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9528 is_sr_mono_method (MonoClass *class)
9530 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9534 is_sr_mono_cmethod (MonoClass *class)
9536 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9540 is_sr_mono_generic_method (MonoClass *class)
9542 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9546 is_sr_mono_generic_cmethod (MonoClass *class)
9548 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9552 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9554 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9558 is_usertype (MonoReflectionType *ref)
9560 MonoClass *class = mono_object_class (ref);
9561 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9564 static MonoReflectionType*
9565 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9567 if (!type || type->type)
9570 if (is_usertype (type)) {
9571 type = mono_reflection_type_get_underlying_system_type (type);
9572 if (is_usertype (type))
9573 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9579 * Encode a value in a custom attribute stream of bytes.
9580 * The value to encode is either supplied as an object in argument val
9581 * (valuetypes are boxed), or as a pointer to the data in the
9583 * @type represents the type of the value
9584 * @buffer is the start of the buffer
9585 * @p the current position in the buffer
9586 * @buflen contains the size of the buffer and is used to return the new buffer size
9587 * if this needs to be realloced.
9588 * @retbuffer and @retp return the start and the position of the buffer
9591 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9593 MonoTypeEnum simple_type;
9595 if ((p-buffer) + 10 >= *buflen) {
9598 newbuf = g_realloc (buffer, *buflen);
9599 p = newbuf + (p-buffer);
9603 argval = ((char*)arg + sizeof (MonoObject));
9604 simple_type = type->type;
9606 switch (simple_type) {
9607 case MONO_TYPE_BOOLEAN:
9612 case MONO_TYPE_CHAR:
9615 swap_with_size (p, argval, 2, 1);
9621 swap_with_size (p, argval, 4, 1);
9625 swap_with_size (p, argval, 8, 1);
9630 swap_with_size (p, argval, 8, 1);
9633 case MONO_TYPE_VALUETYPE:
9634 if (type->data.klass->enumtype) {
9635 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9638 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9641 case MONO_TYPE_STRING: {
9648 str = mono_string_to_utf8 ((MonoString*)arg);
9649 slen = strlen (str);
9650 if ((p-buffer) + 10 + slen >= *buflen) {
9654 newbuf = g_realloc (buffer, *buflen);
9655 p = newbuf + (p-buffer);
9658 mono_metadata_encode_value (slen, p, &p);
9659 memcpy (p, str, slen);
9664 case MONO_TYPE_CLASS: {
9672 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9673 slen = strlen (str);
9674 if ((p-buffer) + 10 + slen >= *buflen) {
9678 newbuf = g_realloc (buffer, *buflen);
9679 p = newbuf + (p-buffer);
9682 mono_metadata_encode_value (slen, p, &p);
9683 memcpy (p, str, slen);
9688 case MONO_TYPE_SZARRAY: {
9690 MonoClass *eclass, *arg_eclass;
9693 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9696 len = mono_array_length ((MonoArray*)arg);
9698 *p++ = (len >> 8) & 0xff;
9699 *p++ = (len >> 16) & 0xff;
9700 *p++ = (len >> 24) & 0xff;
9702 *retbuffer = buffer;
9703 eclass = type->data.klass;
9704 arg_eclass = mono_object_class (arg)->element_class;
9707 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9708 eclass = mono_defaults.object_class;
9710 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9711 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9712 int elsize = mono_class_array_element_size (arg_eclass);
9713 for (i = 0; i < len; ++i) {
9714 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9717 } else if (eclass->valuetype && arg_eclass->valuetype) {
9718 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9719 int elsize = mono_class_array_element_size (eclass);
9720 for (i = 0; i < len; ++i) {
9721 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9725 for (i = 0; i < len; ++i) {
9726 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9731 case MONO_TYPE_OBJECT: {
9737 * The parameter type is 'object' but the type of the actual
9738 * argument is not. So we have to add type information to the blob
9739 * too. This is completely undocumented in the spec.
9743 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9748 klass = mono_object_class (arg);
9750 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9753 } else if (klass->enumtype) {
9755 } else if (klass == mono_defaults.string_class) {
9756 simple_type = MONO_TYPE_STRING;
9759 } else if (klass->rank == 1) {
9761 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9762 /* See Partition II, Appendix B3 */
9765 *p++ = klass->element_class->byval_arg.type;
9766 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9768 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9769 *p++ = simple_type = klass->byval_arg.type;
9772 g_error ("unhandled type in custom attr");
9774 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9775 slen = strlen (str);
9776 if ((p-buffer) + 10 + slen >= *buflen) {
9780 newbuf = g_realloc (buffer, *buflen);
9781 p = newbuf + (p-buffer);
9784 mono_metadata_encode_value (slen, p, &p);
9785 memcpy (p, str, slen);
9788 simple_type = mono_class_enum_basetype (klass)->type;
9792 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9795 *retbuffer = buffer;
9799 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9801 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9802 char *str = type_get_qualified_name (type, NULL);
9803 int slen = strlen (str);
9807 * This seems to be optional...
9810 mono_metadata_encode_value (slen, p, &p);
9811 memcpy (p, str, slen);
9814 } else if (type->type == MONO_TYPE_OBJECT) {
9816 } else if (type->type == MONO_TYPE_CLASS) {
9817 /* it should be a type: encode_cattr_value () has the check */
9820 mono_metadata_encode_value (type->type, p, &p);
9821 if (type->type == MONO_TYPE_SZARRAY)
9822 /* See the examples in Partition VI, Annex B */
9823 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9829 #ifndef DISABLE_REFLECTION_EMIT
9831 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9834 /* Preallocate a large enough buffer */
9835 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9836 char *str = type_get_qualified_name (type, NULL);
9839 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9840 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9846 len += strlen (name);
9848 if ((p-buffer) + 20 + len >= *buflen) {
9852 newbuf = g_realloc (buffer, *buflen);
9853 p = newbuf + (p-buffer);
9857 encode_field_or_prop_type (type, p, &p);
9859 len = strlen (name);
9860 mono_metadata_encode_value (len, p, &p);
9861 memcpy (p, name, len);
9863 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9865 *retbuffer = buffer;
9869 * mono_reflection_get_custom_attrs_blob:
9870 * @ctor: custom attribute constructor
9871 * @ctorArgs: arguments o the constructor
9877 * Creates the blob of data that needs to be saved in the metadata and that represents
9878 * the custom attributed described by @ctor, @ctorArgs etc.
9879 * Returns: a Byte array representing the blob of data.
9882 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9885 MonoMethodSignature *sig;
9890 MONO_ARCH_SAVE_REGS;
9892 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9893 /* sig is freed later so allocate it in the heap */
9894 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9896 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9899 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9901 p = buffer = g_malloc (buflen);
9902 /* write the prolog */
9905 for (i = 0; i < sig->param_count; ++i) {
9906 arg = mono_array_get (ctorArgs, MonoObject*, i);
9907 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9911 i += mono_array_length (properties);
9913 i += mono_array_length (fields);
9915 *p++ = (i >> 8) & 0xff;
9918 for (i = 0; i < mono_array_length (properties); ++i) {
9922 prop = mono_array_get (properties, gpointer, i);
9923 get_prop_name_and_type (prop, &pname, &ptype);
9924 *p++ = 0x54; /* PROPERTY signature */
9925 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9932 for (i = 0; i < mono_array_length (fields); ++i) {
9936 field = mono_array_get (fields, gpointer, i);
9937 get_field_name_and_type (field, &fname, &ftype);
9938 *p++ = 0x53; /* FIELD signature */
9939 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9944 g_assert (p - buffer <= buflen);
9945 buflen = p - buffer;
9946 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9947 p = mono_array_addr (result, char, 0);
9948 memcpy (p, buffer, buflen);
9950 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9956 * mono_reflection_setup_internal_class:
9957 * @tb: a TypeBuilder object
9959 * Creates a MonoClass that represents the TypeBuilder.
9960 * This is a trick that lets us simplify a lot of reflection code
9961 * (and will allow us to support Build and Run assemblies easier).
9964 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9967 MonoClass *klass, *parent;
9969 MONO_ARCH_SAVE_REGS;
9971 RESOLVE_TYPE (tb->parent);
9973 mono_loader_lock ();
9976 /* check so we can compile corlib correctly */
9977 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9978 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9979 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9981 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9987 /* the type has already being created: it means we just have to change the parent */
9988 if (tb->type.type) {
9989 klass = mono_class_from_mono_type (tb->type.type);
9990 klass->parent = NULL;
9991 /* fool mono_class_setup_parent */
9992 klass->supertypes = NULL;
9993 mono_class_setup_parent (klass, parent);
9994 mono_class_setup_mono_type (klass);
9995 mono_loader_unlock ();
9999 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10001 klass->image = &tb->module->dynamic_image->image;
10003 klass->inited = 1; /* we lie to the runtime */
10004 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10005 if (!mono_error_ok (&error))
10007 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10008 if (!mono_error_ok (&error))
10010 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10011 klass->flags = tb->attrs;
10013 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10015 klass->element_class = klass;
10017 if (mono_class_get_ref_info (klass) == NULL) {
10019 mono_class_set_ref_info (klass, tb);
10021 /* Put into cache so mono_class_get_checked () will find it.
10022 Skip nested types as those should not be available on the global scope. */
10023 if (!tb->nesting_type)
10024 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10027 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10028 by performing a mono_class_get which does the full resolution.
10030 Working around this semantics would require us to write a lot of code for no clear advantage.
10032 mono_image_append_class_to_reflection_info_set (klass);
10034 g_assert (mono_class_get_ref_info (klass) == tb);
10037 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
10038 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
10040 if (parent != NULL) {
10041 mono_class_setup_parent (klass, parent);
10042 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10043 const char *old_n = klass->name;
10044 /* trick to get relative numbering right when compiling corlib */
10045 klass->name = "BuildingObject";
10046 mono_class_setup_parent (klass, mono_defaults.object_class);
10047 klass->name = old_n;
10050 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10051 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10052 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10053 klass->instance_size = sizeof (MonoObject);
10054 klass->size_inited = 1;
10055 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10058 mono_class_setup_mono_type (klass);
10060 mono_class_setup_supertypes (klass);
10063 * FIXME: handle interfaces.
10066 tb->type.type = &klass->byval_arg;
10068 if (tb->nesting_type) {
10069 g_assert (tb->nesting_type->type);
10070 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10073 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10075 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10077 mono_loader_unlock ();
10081 mono_loader_unlock ();
10082 mono_error_raise_exception (&error);
10086 * mono_reflection_setup_generic_class:
10087 * @tb: a TypeBuilder object
10089 * Setup the generic class before adding the first generic parameter.
10092 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10097 * mono_reflection_create_generic_class:
10098 * @tb: a TypeBuilder object
10100 * Creates the generic class after all generic parameters have been added.
10103 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10108 MONO_ARCH_SAVE_REGS;
10110 klass = mono_class_from_mono_type (tb->type.type);
10112 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10114 if (klass->generic_container || (count == 0))
10117 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10119 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10121 klass->generic_container->owner.klass = klass;
10122 klass->generic_container->type_argc = count;
10123 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10125 klass->is_generic = 1;
10127 for (i = 0; i < count; i++) {
10128 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10129 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10130 klass->generic_container->type_params [i] = *param;
10131 /*Make sure we are a diferent type instance */
10132 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10133 klass->generic_container->type_params [i].info.pklass = NULL;
10134 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10136 g_assert (klass->generic_container->type_params [i].param.owner);
10139 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10143 * mono_reflection_create_internal_class:
10144 * @tb: a TypeBuilder object
10146 * Actually create the MonoClass that is associated with the TypeBuilder.
10149 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10153 MONO_ARCH_SAVE_REGS;
10155 klass = mono_class_from_mono_type (tb->type.type);
10157 mono_loader_lock ();
10158 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10159 MonoReflectionFieldBuilder *fb;
10161 MonoType *enum_basetype;
10163 g_assert (tb->fields != NULL);
10164 g_assert (mono_array_length (tb->fields) >= 1);
10166 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10168 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10169 mono_loader_unlock ();
10173 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10174 klass->element_class = mono_class_from_mono_type (enum_basetype);
10175 if (!klass->element_class)
10176 klass->element_class = mono_class_from_mono_type (enum_basetype);
10179 * get the element_class from the current corlib.
10181 ec = default_class_from_mono_type (enum_basetype);
10182 klass->instance_size = ec->instance_size;
10183 klass->size_inited = 1;
10185 * this is almost safe to do with enums and it's needed to be able
10186 * to create objects of the enum type (for use in SetConstant).
10188 /* FIXME: Does this mean enums can't have method overrides ? */
10189 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10191 mono_loader_unlock ();
10194 static MonoMarshalSpec*
10195 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10196 MonoReflectionMarshal *minfo)
10198 MonoMarshalSpec *res;
10200 res = image_g_new0 (image, MonoMarshalSpec, 1);
10201 res->native = minfo->type;
10203 switch (minfo->type) {
10204 case MONO_NATIVE_LPARRAY:
10205 res->data.array_data.elem_type = minfo->eltype;
10206 if (minfo->has_size) {
10207 res->data.array_data.param_num = minfo->param_num;
10208 res->data.array_data.num_elem = minfo->count;
10209 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10212 res->data.array_data.param_num = -1;
10213 res->data.array_data.num_elem = -1;
10214 res->data.array_data.elem_mult = -1;
10218 case MONO_NATIVE_BYVALTSTR:
10219 case MONO_NATIVE_BYVALARRAY:
10220 res->data.array_data.num_elem = minfo->count;
10223 case MONO_NATIVE_CUSTOM:
10224 if (minfo->marshaltyperef)
10225 res->data.custom_data.custom_name =
10226 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10227 if (minfo->mcookie)
10228 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10237 #endif /* !DISABLE_REFLECTION_EMIT */
10239 MonoReflectionMarshalAsAttribute*
10240 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10241 MonoMarshalSpec *spec)
10243 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10244 MonoReflectionMarshalAsAttribute *minfo;
10247 if (!System_Reflection_Emit_MarshalAsAttribute) {
10248 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10249 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10250 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10253 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10254 minfo->utype = spec->native;
10256 switch (minfo->utype) {
10257 case MONO_NATIVE_LPARRAY:
10258 minfo->array_subtype = spec->data.array_data.elem_type;
10259 minfo->size_const = spec->data.array_data.num_elem;
10260 if (spec->data.array_data.param_num != -1)
10261 minfo->size_param_index = spec->data.array_data.param_num;
10264 case MONO_NATIVE_BYVALTSTR:
10265 case MONO_NATIVE_BYVALARRAY:
10266 minfo->size_const = spec->data.array_data.num_elem;
10269 case MONO_NATIVE_CUSTOM:
10270 if (spec->data.custom_data.custom_name) {
10271 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10273 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10275 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10277 if (spec->data.custom_data.cookie)
10278 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10288 #ifndef DISABLE_REFLECTION_EMIT
10290 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10291 ReflectionMethodBuilder *rmb,
10292 MonoMethodSignature *sig)
10296 MonoMethodWrapper *wrapperm;
10297 MonoMarshalSpec **specs;
10298 MonoReflectionMethodAux *method_aux;
10303 mono_error_init (&error);
10305 * Methods created using a MethodBuilder should have their memory allocated
10306 * inside the image mempool, while dynamic methods should have their memory
10309 dynamic = rmb->refs != NULL;
10310 image = dynamic ? NULL : klass->image;
10313 g_assert (!klass->generic_class);
10315 mono_loader_lock ();
10317 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10318 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10319 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10321 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10323 wrapperm = (MonoMethodWrapper*)m;
10325 m->dynamic = dynamic;
10327 m->flags = rmb->attrs;
10328 m->iflags = rmb->iattrs;
10329 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10331 m->signature = sig;
10332 m->sre_method = TRUE;
10333 m->skip_visibility = rmb->skip_visibility;
10334 if (rmb->table_idx)
10335 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10337 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10338 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10339 m->string_ctor = 1;
10341 m->signature->pinvoke = 1;
10342 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10343 m->signature->pinvoke = 1;
10345 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10347 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10348 g_assert (mono_error_ok (&error));
10349 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10350 g_assert (mono_error_ok (&error));
10352 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10354 if (image_is_dynamic (klass->image))
10355 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10357 mono_loader_unlock ();
10360 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10361 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10362 MonoMethodHeader *header;
10364 gint32 max_stack, i;
10365 gint32 num_locals = 0;
10366 gint32 num_clauses = 0;
10370 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10371 code_size = rmb->ilgen->code_len;
10372 max_stack = rmb->ilgen->max_stack;
10373 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10374 if (rmb->ilgen->ex_handlers)
10375 num_clauses = method_count_clauses (rmb->ilgen);
10378 code = mono_array_addr (rmb->code, guint8, 0);
10379 code_size = mono_array_length (rmb->code);
10380 /* we probably need to run a verifier on the code... */
10390 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10391 header->code_size = code_size;
10392 header->code = image_g_malloc (image, code_size);
10393 memcpy ((char*)header->code, code, code_size);
10394 header->max_stack = max_stack;
10395 header->init_locals = rmb->init_locals;
10396 header->num_locals = num_locals;
10398 for (i = 0; i < num_locals; ++i) {
10399 MonoReflectionLocalBuilder *lb =
10400 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10402 header->locals [i] = image_g_new0 (image, MonoType, 1);
10403 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10406 header->num_clauses = num_clauses;
10408 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10409 rmb->ilgen, num_clauses);
10412 wrapperm->header = header;
10415 if (rmb->generic_params) {
10416 int count = mono_array_length (rmb->generic_params);
10417 MonoGenericContainer *container = rmb->generic_container;
10419 g_assert (container);
10421 container->type_argc = count;
10422 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10423 container->owner.method = m;
10425 m->is_generic = TRUE;
10426 mono_method_set_generic_container (m, container);
10428 for (i = 0; i < count; i++) {
10429 MonoReflectionGenericParam *gp =
10430 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10431 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10432 container->type_params [i] = *param;
10436 * The method signature might have pointers to generic parameters that belong to other methods.
10437 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10438 * generic parameters.
10440 for (i = 0; i < m->signature->param_count; ++i) {
10441 MonoType *t = m->signature->params [i];
10442 if (t->type == MONO_TYPE_MVAR) {
10443 MonoGenericParam *gparam = t->data.generic_param;
10444 if (gparam->num < count) {
10445 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10446 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10452 if (klass->generic_container) {
10453 container->parent = klass->generic_container;
10454 container->context.class_inst = klass->generic_container->context.class_inst;
10456 container->context.method_inst = mono_get_shared_generic_inst (container);
10460 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10464 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10466 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10467 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10468 for (i = 0; i < rmb->nrefs; ++i)
10469 data [i + 1] = rmb->refs [i];
10474 /* Parameter info */
10477 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10478 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10479 for (i = 0; i <= m->signature->param_count; ++i) {
10480 MonoReflectionParamBuilder *pb;
10481 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10482 if ((i > 0) && (pb->attrs)) {
10483 /* Make a copy since it might point to a shared type structure */
10484 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10485 m->signature->params [i - 1]->attrs = pb->attrs;
10488 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10489 MonoDynamicImage *assembly;
10490 guint32 idx, def_type, len;
10494 if (!method_aux->param_defaults) {
10495 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10496 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10498 assembly = (MonoDynamicImage*)klass->image;
10499 idx = encode_constant (assembly, pb->def_value, &def_type);
10500 /* Copy the data from the blob since it might get realloc-ed */
10501 p = assembly->blob.data + idx;
10502 len = mono_metadata_decode_blob_size (p, &p2);
10504 method_aux->param_defaults [i] = image_g_malloc (image, len);
10505 method_aux->param_default_types [i] = def_type;
10506 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10510 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10511 g_assert (mono_error_ok (&error));
10514 if (!method_aux->param_cattr)
10515 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10516 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10522 /* Parameter marshalling */
10525 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10526 MonoReflectionParamBuilder *pb;
10527 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10528 if (pb->marshal_info) {
10530 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10531 specs [pb->position] =
10532 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10536 if (specs != NULL) {
10538 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10539 method_aux->param_marshall = specs;
10542 if (image_is_dynamic (klass->image) && method_aux)
10543 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10545 mono_loader_unlock ();
10551 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10553 ReflectionMethodBuilder rmb;
10554 MonoMethodSignature *sig;
10556 mono_loader_lock ();
10557 sig = ctor_builder_to_signature (klass->image, mb);
10558 mono_loader_unlock ();
10560 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10562 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10563 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10565 /* If we are in a generic class, we might be called multiple times from inflate_method */
10566 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10567 /* ilgen is no longer needed */
10571 return mb->mhandle;
10575 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10577 ReflectionMethodBuilder rmb;
10578 MonoMethodSignature *sig;
10580 mono_loader_lock ();
10581 sig = method_builder_to_signature (klass->image, mb);
10582 mono_loader_unlock ();
10584 reflection_methodbuilder_from_method_builder (&rmb, mb);
10586 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10587 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10589 /* If we are in a generic class, we might be called multiple times from inflate_method */
10590 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10591 /* ilgen is no longer needed */
10594 return mb->mhandle;
10597 static MonoClassField*
10598 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10600 MonoClassField *field;
10604 field = g_new0 (MonoClassField, 1);
10606 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10607 g_assert (mono_error_ok (&error));
10608 if (fb->attrs || fb->modreq || fb->modopt) {
10609 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10610 field->type->attrs = fb->attrs;
10612 g_assert (image_is_dynamic (klass->image));
10613 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10614 g_free (field->type);
10615 field->type = mono_metadata_type_dup (klass->image, custom);
10618 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10620 if (fb->offset != -1)
10621 field->offset = fb->offset;
10622 field->parent = klass;
10623 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10625 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10632 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10635 MonoReflectionTypeBuilder *tb = NULL;
10636 gboolean is_dynamic = FALSE;
10637 MonoDomain *domain;
10638 MonoClass *geninst;
10640 mono_loader_lock ();
10642 domain = mono_object_domain (type);
10644 if (is_sre_type_builder (mono_object_class (type))) {
10645 tb = (MonoReflectionTypeBuilder *) type;
10648 } else if (is_sre_generic_instance (mono_object_class (type))) {
10649 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10650 MonoReflectionType *gtd = rgi->generic_type;
10652 if (is_sre_type_builder (mono_object_class (gtd))) {
10653 tb = (MonoReflectionTypeBuilder *)gtd;
10658 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10659 if (tb && tb->generic_container)
10660 mono_reflection_create_generic_class (tb);
10662 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10663 if (!klass->generic_container) {
10664 mono_loader_unlock ();
10668 if (klass->wastypebuilder) {
10669 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10674 mono_loader_unlock ();
10676 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10678 return &geninst->byval_arg;
10682 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10684 MonoGenericClass *gclass;
10685 MonoGenericInst *inst;
10687 g_assert (klass->generic_container);
10689 inst = mono_metadata_get_generic_inst (type_argc, types);
10690 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10692 return mono_generic_class_get_class (gclass);
10695 MonoReflectionMethod*
10696 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10699 MonoMethod *method, *inflated;
10700 MonoMethodInflated *imethod;
10701 MonoGenericContext tmp_context;
10702 MonoGenericInst *ginst;
10703 MonoType **type_argv;
10706 MONO_ARCH_SAVE_REGS;
10708 /*FIXME but this no longer should happen*/
10709 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10710 #ifndef DISABLE_REFLECTION_EMIT
10711 MonoReflectionMethodBuilder *mb = NULL;
10712 MonoReflectionTypeBuilder *tb;
10715 mb = (MonoReflectionMethodBuilder *) rmethod;
10716 tb = (MonoReflectionTypeBuilder *) mb->type;
10717 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10719 method = methodbuilder_to_mono_method (klass, mb);
10721 g_assert_not_reached ();
10725 method = rmethod->method;
10728 klass = method->klass;
10730 if (method->is_inflated)
10731 method = ((MonoMethodInflated *) method)->declaring;
10733 count = mono_method_signature (method)->generic_param_count;
10734 if (count != mono_array_length (types))
10737 type_argv = g_new0 (MonoType *, count);
10738 for (i = 0; i < count; i++) {
10739 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10740 type_argv [i] = mono_reflection_type_get_handle (garg);
10742 ginst = mono_metadata_get_generic_inst (count, type_argv);
10743 g_free (type_argv);
10745 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10746 tmp_context.method_inst = ginst;
10748 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10749 imethod = (MonoMethodInflated *) inflated;
10751 /*FIXME but I think this is no longer necessary*/
10752 if (image_is_dynamic (method->klass->image)) {
10753 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10755 * This table maps metadata structures representing inflated methods/fields
10756 * to the reflection objects representing their generic definitions.
10758 mono_image_lock ((MonoImage*)image);
10759 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10760 mono_image_unlock ((MonoImage*)image);
10763 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10764 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10766 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10769 #ifndef DISABLE_REFLECTION_EMIT
10771 static MonoMethod *
10772 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10774 MonoMethodInflated *imethod;
10775 MonoGenericContext *context;
10779 * With generic code sharing the klass might not be inflated.
10780 * This can happen because classes inflated with their own
10781 * type arguments are "normalized" to the uninflated class.
10783 if (!klass->generic_class)
10786 context = mono_class_get_context (klass);
10788 if (klass->method.count && klass->methods) {
10789 /* Find the already created inflated method */
10790 for (i = 0; i < klass->method.count; ++i) {
10791 g_assert (klass->methods [i]->is_inflated);
10792 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10795 g_assert (i < klass->method.count);
10796 imethod = (MonoMethodInflated*)klass->methods [i];
10798 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10801 if (method->is_generic && image_is_dynamic (method->klass->image)) {
10802 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10804 mono_image_lock ((MonoImage*)image);
10805 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10806 mono_image_unlock ((MonoImage*)image);
10808 return (MonoMethod *) imethod;
10811 static MonoMethod *
10812 inflate_method (MonoReflectionType *type, MonoObject *obj)
10814 MonoMethod *method;
10817 MonoClass *type_class = mono_object_class (type);
10819 if (is_sre_generic_instance (type_class)) {
10820 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10821 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10822 } else if (is_sre_type_builder (type_class)) {
10823 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10824 } else if (type->type) {
10825 gklass = mono_class_from_mono_type (type->type);
10826 gklass = mono_class_get_generic_type_definition (gklass);
10828 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10831 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10832 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10833 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10835 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10836 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10837 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10838 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10839 method = ((MonoReflectionMethod *) obj)->method;
10841 method = NULL; /* prevent compiler warning */
10842 g_error ("can't handle type %s", obj->vtable->klass->name);
10845 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10848 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10850 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10852 MonoGenericClass *gclass;
10853 MonoDynamicGenericClass *dgclass;
10854 MonoClass *klass, *gklass;
10858 MONO_ARCH_SAVE_REGS;
10860 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10861 klass = mono_class_from_mono_type (gtype);
10862 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10863 gclass = gtype->data.generic_class;
10865 if (!gclass->is_dynamic)
10868 dgclass = (MonoDynamicGenericClass *) gclass;
10870 if (dgclass->initialized)
10873 gklass = gclass->container_class;
10874 mono_class_init (gklass);
10876 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10878 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10879 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10880 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10882 for (i = 0; i < dgclass->count_fields; i++) {
10883 MonoObject *obj = mono_array_get (fields, gpointer, i);
10884 MonoClassField *field, *inflated_field = NULL;
10886 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10887 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10888 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10889 field = ((MonoReflectionField *) obj)->field;
10891 field = NULL; /* prevent compiler warning */
10892 g_assert_not_reached ();
10895 dgclass->fields [i] = *field;
10896 dgclass->fields [i].parent = klass;
10897 dgclass->fields [i].type = mono_class_inflate_generic_type (
10898 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10899 dgclass->field_generic_types [i] = field->type;
10900 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10901 dgclass->field_objects [i] = obj;
10903 if (inflated_field) {
10904 g_free (inflated_field);
10906 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10910 dgclass->initialized = TRUE;
10914 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10916 MonoDynamicGenericClass *dgclass;
10919 g_assert (gclass->is_dynamic);
10921 dgclass = (MonoDynamicGenericClass *)gclass;
10923 for (i = 0; i < dgclass->count_fields; ++i) {
10924 MonoClassField *field = dgclass->fields + i;
10925 mono_metadata_free_type (field->type);
10926 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10931 fix_partial_generic_class (MonoClass *klass)
10933 MonoClass *gklass = klass->generic_class->container_class;
10934 MonoDynamicGenericClass *dgclass;
10937 if (klass->wastypebuilder)
10940 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10941 if (klass->parent != gklass->parent) {
10943 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10944 if (mono_error_ok (&error)) {
10945 MonoClass *parent = mono_class_from_mono_type (parent_type);
10946 mono_metadata_free_type (parent_type);
10947 if (parent != klass->parent) {
10948 /*fool mono_class_setup_parent*/
10949 klass->supertypes = NULL;
10950 mono_class_setup_parent (klass, parent);
10953 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10954 mono_error_cleanup (&error);
10955 if (gklass->wastypebuilder)
10956 klass->wastypebuilder = TRUE;
10961 if (!dgclass->initialized)
10964 if (klass->method.count != gklass->method.count) {
10965 klass->method.count = gklass->method.count;
10966 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10968 for (i = 0; i < klass->method.count; i++) {
10969 klass->methods [i] = mono_class_inflate_generic_method_full (
10970 gklass->methods [i], klass, mono_class_get_context (klass));
10974 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10975 klass->interface_count = gklass->interface_count;
10976 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10977 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10979 for (i = 0; i < gklass->interface_count; ++i) {
10980 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10981 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10982 mono_metadata_free_type (iface_type);
10984 ensure_runtime_vtable (klass->interfaces [i]);
10986 klass->interfaces_inited = 1;
10989 if (klass->field.count != gklass->field.count) {
10990 klass->field.count = gklass->field.count;
10991 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10993 for (i = 0; i < klass->field.count; i++) {
10994 klass->fields [i] = gklass->fields [i];
10995 klass->fields [i].parent = klass;
10996 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11000 /*We can only finish with this klass once it's parent has as well*/
11001 if (gklass->wastypebuilder)
11002 klass->wastypebuilder = TRUE;
11007 ensure_generic_class_runtime_vtable (MonoClass *klass)
11009 MonoClass *gklass = klass->generic_class->container_class;
11011 ensure_runtime_vtable (gklass);
11013 fix_partial_generic_class (klass);
11017 ensure_runtime_vtable (MonoClass *klass)
11019 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11022 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11025 ensure_runtime_vtable (klass->parent);
11028 num = tb->ctors? mono_array_length (tb->ctors): 0;
11029 num += tb->num_methods;
11030 klass->method.count = num;
11031 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11032 num = tb->ctors? mono_array_length (tb->ctors): 0;
11033 for (i = 0; i < num; ++i)
11034 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11035 num = tb->num_methods;
11037 for (i = 0; i < num; ++i)
11038 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11040 if (tb->interfaces) {
11041 klass->interface_count = mono_array_length (tb->interfaces);
11042 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11043 for (i = 0; i < klass->interface_count; ++i) {
11044 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11045 klass->interfaces [i] = mono_class_from_mono_type (iface);
11046 ensure_runtime_vtable (klass->interfaces [i]);
11048 klass->interfaces_inited = 1;
11050 } else if (klass->generic_class){
11051 ensure_generic_class_runtime_vtable (klass);
11054 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11056 for (i = 0; i < klass->method.count; ++i) {
11057 MonoMethod *im = klass->methods [i];
11058 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11059 im->slot = slot_num++;
11062 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11063 mono_class_setup_interface_offsets (klass);
11064 mono_class_setup_interface_id (klass);
11068 * The generic vtable is needed even if image->run is not set since some
11069 * runtime code like ves_icall_Type_GetMethodsByName depends on
11070 * method->slot being defined.
11074 * tb->methods could not be freed since it is used for determining
11075 * overrides during dynamic vtable construction.
11080 mono_reflection_method_get_handle (MonoObject *method)
11082 MonoClass *class = mono_object_class (method);
11083 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11084 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11085 return sr_method->method;
11087 if (is_sre_method_builder (class)) {
11088 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11089 return mb->mhandle;
11091 if (is_sre_method_on_tb_inst (class)) {
11092 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11093 MonoMethod *result;
11094 /*FIXME move this to a proper method and unify with resolve_object*/
11095 if (m->method_args) {
11096 result = mono_reflection_method_on_tb_inst_get_handle (m);
11098 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11099 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11100 MonoMethod *mono_method;
11102 if (is_sre_method_builder (mono_object_class (m->mb)))
11103 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11104 else if (is_sr_mono_method (mono_object_class (m->mb)))
11105 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11107 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)));
11109 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11114 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11119 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11121 MonoReflectionTypeBuilder *tb;
11123 MonoReflectionMethod *m;
11126 *num_overrides = 0;
11128 g_assert (image_is_dynamic (klass->image));
11130 if (!mono_class_get_ref_info (klass))
11133 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11135 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11139 for (i = 0; i < tb->num_methods; ++i) {
11140 MonoReflectionMethodBuilder *mb =
11141 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11142 if (mb->override_methods)
11143 onum += mono_array_length (mb->override_methods);
11148 *overrides = g_new0 (MonoMethod*, onum * 2);
11151 for (i = 0; i < tb->num_methods; ++i) {
11152 MonoReflectionMethodBuilder *mb =
11153 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11154 if (mb->override_methods) {
11155 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11156 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11158 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11159 (*overrides) [onum * 2 + 1] = mb->mhandle;
11161 g_assert (mb->mhandle);
11169 *num_overrides = onum;
11173 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11175 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11176 MonoReflectionFieldBuilder *fb;
11177 MonoClassField *field;
11178 MonoImage *image = klass->image;
11179 const char *p, *p2;
11181 guint32 len, idx, real_size = 0;
11183 klass->field.count = tb->num_fields;
11184 klass->field.first = 0;
11186 mono_error_init (error);
11188 if (tb->class_size) {
11189 if ((tb->packing_size & 0xfffffff0) != 0) {
11190 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11191 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11194 klass->packing_size = tb->packing_size;
11195 real_size = klass->instance_size + tb->class_size;
11198 if (!klass->field.count) {
11199 klass->instance_size = MAX (klass->instance_size, real_size);
11203 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11204 mono_class_alloc_ext (klass);
11205 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11207 This is, guess what, a hack.
11208 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11209 On the static path no field class is resolved, only types are built. This is the right thing to do
11211 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11213 klass->size_inited = 1;
11215 for (i = 0; i < klass->field.count; ++i) {
11216 MonoArray *rva_data;
11217 fb = mono_array_get (tb->fields, gpointer, i);
11218 field = &klass->fields [i];
11219 field->name = mono_string_to_utf8_image (image, fb->name, error);
11220 if (!mono_error_ok (error))
11223 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11224 field->type->attrs = fb->attrs;
11226 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11229 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11230 char *base = mono_array_addr (rva_data, char, 0);
11231 size_t size = mono_array_length (rva_data);
11232 char *data = mono_image_alloc (klass->image, size);
11233 memcpy (data, base, size);
11234 klass->ext->field_def_values [i].data = data;
11236 if (fb->offset != -1)
11237 field->offset = fb->offset;
11238 field->parent = klass;
11239 fb->handle = field;
11240 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11242 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11243 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11245 if (fb->def_value) {
11246 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11247 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11248 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11249 /* Copy the data from the blob since it might get realloc-ed */
11250 p = assembly->blob.data + idx;
11251 len = mono_metadata_decode_blob_size (p, &p2);
11253 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11254 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11258 klass->instance_size = MAX (klass->instance_size, real_size);
11259 mono_class_layout_fields (klass);
11263 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11265 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11266 MonoReflectionPropertyBuilder *pb;
11267 MonoImage *image = klass->image;
11268 MonoProperty *properties;
11271 mono_error_init (error);
11274 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11276 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11277 klass->ext->property.first = 0;
11279 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11280 klass->ext->properties = properties;
11281 for (i = 0; i < klass->ext->property.count; ++i) {
11282 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11283 properties [i].parent = klass;
11284 properties [i].attrs = pb->attrs;
11285 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11286 if (!mono_error_ok (error))
11288 if (pb->get_method)
11289 properties [i].get = pb->get_method->mhandle;
11290 if (pb->set_method)
11291 properties [i].set = pb->set_method->mhandle;
11293 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11294 if (pb->def_value) {
11296 const char *p, *p2;
11297 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11298 if (!klass->ext->prop_def_values)
11299 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11300 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11301 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11302 /* Copy the data from the blob since it might get realloc-ed */
11303 p = assembly->blob.data + idx;
11304 len = mono_metadata_decode_blob_size (p, &p2);
11306 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11307 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11312 MonoReflectionEvent *
11313 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11315 MonoEvent *event = g_new0 (MonoEvent, 1);
11318 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11320 event->parent = klass;
11321 event->attrs = eb->attrs;
11322 event->name = mono_string_to_utf8 (eb->name);
11323 if (eb->add_method)
11324 event->add = eb->add_method->mhandle;
11325 if (eb->remove_method)
11326 event->remove = eb->remove_method->mhandle;
11327 if (eb->raise_method)
11328 event->raise = eb->raise_method->mhandle;
11330 #ifndef MONO_SMALL_CONFIG
11331 if (eb->other_methods) {
11333 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11334 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11335 MonoReflectionMethodBuilder *mb =
11336 mono_array_get (eb->other_methods,
11337 MonoReflectionMethodBuilder*, j);
11338 event->other [j] = mb->mhandle;
11343 return mono_event_get_object (mono_object_domain (tb), klass, event);
11347 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11349 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11350 MonoReflectionEventBuilder *eb;
11351 MonoImage *image = klass->image;
11355 mono_error_init (error);
11358 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11360 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11361 klass->ext->event.first = 0;
11363 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11364 klass->ext->events = events;
11365 for (i = 0; i < klass->ext->event.count; ++i) {
11366 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11367 events [i].parent = klass;
11368 events [i].attrs = eb->attrs;
11369 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11370 if (!mono_error_ok (error))
11372 if (eb->add_method)
11373 events [i].add = eb->add_method->mhandle;
11374 if (eb->remove_method)
11375 events [i].remove = eb->remove_method->mhandle;
11376 if (eb->raise_method)
11377 events [i].raise = eb->raise_method->mhandle;
11379 #ifndef MONO_SMALL_CONFIG
11380 if (eb->other_methods) {
11382 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11383 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11384 MonoReflectionMethodBuilder *mb =
11385 mono_array_get (eb->other_methods,
11386 MonoReflectionMethodBuilder*, j);
11387 events [i].other [j] = mb->mhandle;
11391 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11396 remove_instantiations_of_and_ensure_contents (gpointer key,
11398 gpointer user_data)
11400 MonoType *type = (MonoType*)key;
11401 MonoClass *klass = (MonoClass*)user_data;
11403 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11404 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11411 check_array_for_usertypes (MonoArray *arr)
11418 for (i = 0; i < mono_array_length (arr); ++i)
11419 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11422 MonoReflectionType*
11423 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11427 MonoDomain* domain;
11428 MonoReflectionType* res;
11431 MONO_ARCH_SAVE_REGS;
11433 domain = mono_object_domain (tb);
11434 klass = mono_class_from_mono_type (tb->type.type);
11437 * Check for user defined Type subclasses.
11439 RESOLVE_TYPE (tb->parent);
11440 check_array_for_usertypes (tb->interfaces);
11442 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11443 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11445 RESOLVE_TYPE (fb->type);
11446 check_array_for_usertypes (fb->modreq);
11447 check_array_for_usertypes (fb->modopt);
11448 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11449 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11454 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11455 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11457 RESOLVE_TYPE (mb->rtype);
11458 check_array_for_usertypes (mb->return_modreq);
11459 check_array_for_usertypes (mb->return_modopt);
11460 check_array_for_usertypes (mb->parameters);
11461 if (mb->param_modreq)
11462 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11463 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11464 if (mb->param_modopt)
11465 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11466 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11471 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11472 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11474 check_array_for_usertypes (mb->parameters);
11475 if (mb->param_modreq)
11476 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11477 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11478 if (mb->param_modopt)
11479 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11480 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11485 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11488 * we need to lock the domain because the lock will be taken inside
11489 * So, we need to keep the locking order correct.
11491 mono_loader_lock ();
11492 mono_domain_lock (domain);
11493 if (klass->wastypebuilder) {
11494 mono_domain_unlock (domain);
11495 mono_loader_unlock ();
11496 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11499 * Fields to set in klass:
11500 * the various flags: delegate/unicode/contextbound etc.
11502 klass->flags = tb->attrs;
11503 klass->has_cctor = 1;
11504 klass->has_finalize = 1;
11505 klass->has_finalize_inited = 1;
11507 mono_class_setup_parent (klass, klass->parent);
11508 /* fool mono_class_setup_supertypes */
11509 klass->supertypes = NULL;
11510 mono_class_setup_supertypes (klass);
11511 mono_class_setup_mono_type (klass);
11514 if (!((MonoDynamicImage*)klass->image)->run) {
11515 if (klass->generic_container) {
11516 /* FIXME: The code below can't handle generic classes */
11517 klass->wastypebuilder = TRUE;
11518 mono_loader_unlock ();
11519 mono_domain_unlock (domain);
11520 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11525 /* enums are done right away */
11526 if (!klass->enumtype)
11527 ensure_runtime_vtable (klass);
11529 if (tb->subtypes) {
11530 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11531 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11532 mono_class_alloc_ext (klass);
11533 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11537 klass->nested_classes_inited = TRUE;
11539 /* fields and object layout */
11540 if (klass->parent) {
11541 if (!klass->parent->size_inited)
11542 mono_class_init (klass->parent);
11543 klass->instance_size = klass->parent->instance_size;
11544 klass->sizes.class_size = 0;
11545 klass->min_align = klass->parent->min_align;
11546 /* if the type has no fields we won't call the field_setup
11547 * routine which sets up klass->has_references.
11549 klass->has_references |= klass->parent->has_references;
11551 klass->instance_size = sizeof (MonoObject);
11552 klass->min_align = 1;
11555 /* FIXME: handle packing_size and instance_size */
11556 typebuilder_setup_fields (klass, &error);
11557 if (!mono_error_ok (&error))
11559 typebuilder_setup_properties (klass, &error);
11560 if (!mono_error_ok (&error))
11563 typebuilder_setup_events (klass, &error);
11564 if (!mono_error_ok (&error))
11567 klass->wastypebuilder = TRUE;
11570 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11571 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11572 * we want to return normal System.MonoType objects, so clear these out from the cache.
11574 * Together with this we must ensure the contents of all instances to match the created type.
11576 if (domain->type_hash && klass->generic_container)
11577 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11579 mono_domain_unlock (domain);
11580 mono_loader_unlock ();
11582 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11583 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11584 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11587 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11588 g_assert (res != (MonoReflectionType*)tb);
11593 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11594 klass->wastypebuilder = TRUE;
11595 mono_domain_unlock (domain);
11596 mono_loader_unlock ();
11597 mono_error_raise_exception (&error);
11602 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11604 MonoGenericParamFull *param;
11609 MONO_ARCH_SAVE_REGS;
11611 image = &gparam->tbuilder->module->dynamic_image->image;
11613 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11615 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11616 g_assert (mono_error_ok (&error));
11617 param->param.num = gparam->index;
11619 if (gparam->mbuilder) {
11620 if (!gparam->mbuilder->generic_container) {
11621 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11622 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11623 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11624 gparam->mbuilder->generic_container->is_method = TRUE;
11626 * Cannot set owner.method, since the MonoMethod is not created yet.
11627 * Set the image field instead, so type_in_image () works.
11629 gparam->mbuilder->generic_container->image = klass->image;
11631 param->param.owner = gparam->mbuilder->generic_container;
11632 } else if (gparam->tbuilder) {
11633 if (!gparam->tbuilder->generic_container) {
11634 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11635 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11636 gparam->tbuilder->generic_container->owner.klass = klass;
11638 param->param.owner = gparam->tbuilder->generic_container;
11641 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11643 gparam->type.type = &pklass->byval_arg;
11645 mono_class_set_ref_info (pklass, gparam);
11646 mono_image_append_class_to_reflection_info_set (pklass);
11650 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11652 MonoReflectionModuleBuilder *module = sig->module;
11653 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11654 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11659 check_array_for_usertypes (sig->arguments);
11661 sigbuffer_init (&buf, 32);
11663 sigbuffer_add_value (&buf, 0x07);
11664 sigbuffer_add_value (&buf, na);
11665 if (assembly != NULL){
11666 for (i = 0; i < na; ++i) {
11667 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11668 encode_reflection_type (assembly, type, &buf);
11672 buflen = buf.p - buf.buf;
11673 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11674 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11675 sigbuffer_free (&buf);
11681 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11683 MonoDynamicImage *assembly = sig->module->dynamic_image;
11684 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11689 check_array_for_usertypes (sig->arguments);
11691 sigbuffer_init (&buf, 32);
11693 sigbuffer_add_value (&buf, 0x06);
11694 for (i = 0; i < na; ++i) {
11695 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11696 encode_reflection_type (assembly, type, &buf);
11699 buflen = buf.p - buf.buf;
11700 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11701 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11702 sigbuffer_free (&buf);
11708 MonoMethod *handle;
11709 MonoDomain *domain;
11710 } DynamicMethodReleaseData;
11713 * The runtime automatically clean up those after finalization.
11715 static MonoReferenceQueue *dynamic_method_queue;
11718 free_dynamic_method (void *dynamic_method)
11720 DynamicMethodReleaseData *data = dynamic_method;
11722 mono_runtime_free_method (data->domain, data->handle);
11727 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11729 MonoReferenceQueue *queue;
11730 MonoMethod *handle;
11731 DynamicMethodReleaseData *release_data;
11732 ReflectionMethodBuilder rmb;
11733 MonoMethodSignature *sig;
11738 if (mono_runtime_is_shutting_down ())
11739 mono_raise_exception (mono_get_exception_invalid_operation (""));
11741 if (!(queue = dynamic_method_queue)) {
11742 mono_loader_lock ();
11743 if (!(queue = dynamic_method_queue))
11744 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11745 mono_loader_unlock ();
11748 sig = dynamic_method_to_signature (mb);
11750 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11753 * Resolve references.
11756 * Every second entry in the refs array is reserved for storing handle_class,
11757 * which is needed by the ldtoken implementation in the JIT.
11759 rmb.nrefs = mb->nrefs;
11760 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11761 for (i = 0; i < mb->nrefs; i += 2) {
11762 MonoClass *handle_class;
11764 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11766 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11767 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11769 * The referenced DynamicMethod should already be created by the managed
11770 * code, except in the case of circular references. In that case, we store
11771 * method in the refs array, and fix it up later when the referenced
11772 * DynamicMethod is created.
11774 if (method->mhandle) {
11775 ref = method->mhandle;
11777 /* FIXME: GC object stored in unmanaged memory */
11780 /* FIXME: GC object stored in unmanaged memory */
11781 method->referenced_by = g_slist_append (method->referenced_by, mb);
11783 handle_class = mono_defaults.methodhandle_class;
11785 MonoException *ex = NULL;
11786 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11788 ex = mono_get_exception_type_load (NULL, NULL);
11789 else if (mono_security_core_clr_enabled ())
11790 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11794 mono_raise_exception (ex);
11799 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11800 rmb.refs [i + 1] = handle_class;
11803 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11805 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11806 release_data = g_new (DynamicMethodReleaseData, 1);
11807 release_data->handle = handle;
11808 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11809 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11810 g_free (release_data);
11812 /* Fix up refs entries pointing at us */
11813 for (l = mb->referenced_by; l; l = l->next) {
11814 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11815 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11818 g_assert (method->mhandle);
11820 data = (gpointer*)wrapper->method_data;
11821 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11822 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11823 data [i + 1] = mb->mhandle;
11826 g_slist_free (mb->referenced_by);
11830 /* ilgen is no longer needed */
11834 #endif /* DISABLE_REFLECTION_EMIT */
11838 * mono_reflection_is_valid_dynamic_token:
11840 * Returns TRUE if token is valid.
11844 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11846 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11849 MonoMethodSignature *
11850 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11852 MonoMethodSignature *sig;
11853 g_assert (image_is_dynamic (image));
11855 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11859 return mono_method_signature (method);
11862 #ifndef DISABLE_REFLECTION_EMIT
11865 * mono_reflection_lookup_dynamic_token:
11867 * Finish the Builder object pointed to by TOKEN and return the corresponding
11868 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11869 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11872 * LOCKING: Take the loader lock
11875 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11877 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11881 mono_loader_lock ();
11882 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11883 mono_loader_unlock ();
11886 g_error ("Could not find required dynamic token 0x%08x", token);
11892 handle_class = &klass;
11893 return resolve_object (image, obj, handle_class, context);
11897 * ensure_complete_type:
11899 * Ensure that KLASS is completed if it is a dynamic type, or references
11903 ensure_complete_type (MonoClass *klass)
11905 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11906 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11908 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11910 // Asserting here could break a lot of code
11911 //g_assert (klass->wastypebuilder);
11914 if (klass->generic_class) {
11915 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11918 for (i = 0; i < inst->type_argc; ++i) {
11919 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11925 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11927 gpointer result = NULL;
11929 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11930 result = mono_string_intern ((MonoString*)obj);
11931 *handle_class = mono_defaults.string_class;
11933 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11934 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11935 MonoClass *mc = mono_class_from_mono_type (type);
11936 if (!mono_class_init (mc))
11937 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11940 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11941 result = mono_class_from_mono_type (inflated);
11942 mono_metadata_free_type (inflated);
11944 result = mono_class_from_mono_type (type);
11946 *handle_class = mono_defaults.typehandle_class;
11948 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11949 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11950 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11951 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11952 result = ((MonoReflectionMethod*)obj)->method;
11954 result = mono_class_inflate_generic_method (result, context);
11955 *handle_class = mono_defaults.methodhandle_class;
11957 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11958 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11959 result = mb->mhandle;
11961 /* Type is not yet created */
11962 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11964 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11967 * Hopefully this has been filled in by calling CreateType() on the
11971 * TODO: This won't work if the application finishes another
11972 * TypeBuilder instance instead of this one.
11974 result = mb->mhandle;
11977 result = mono_class_inflate_generic_method (result, context);
11978 *handle_class = mono_defaults.methodhandle_class;
11979 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11980 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11982 result = cb->mhandle;
11984 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11986 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11987 result = cb->mhandle;
11990 result = mono_class_inflate_generic_method (result, context);
11991 *handle_class = mono_defaults.methodhandle_class;
11992 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11993 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11995 ensure_complete_type (field->parent);
11997 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11998 MonoClass *class = mono_class_from_mono_type (inflated);
11999 MonoClassField *inflated_field;
12000 gpointer iter = NULL;
12001 mono_metadata_free_type (inflated);
12002 while ((inflated_field = mono_class_get_fields (class, &iter))) {
12003 if (!strcmp (field->name, inflated_field->name))
12006 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12007 result = inflated_field;
12011 *handle_class = mono_defaults.fieldhandle_class;
12013 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12014 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12015 result = fb->handle;
12018 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12020 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12021 result = fb->handle;
12024 if (fb->handle && fb->handle->parent->generic_container) {
12025 MonoClass *klass = fb->handle->parent;
12026 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12027 MonoClass *inflated = mono_class_from_mono_type (type);
12029 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12031 mono_metadata_free_type (type);
12033 *handle_class = mono_defaults.fieldhandle_class;
12034 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12035 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12036 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12039 klass = type->data.klass;
12040 if (klass->wastypebuilder) {
12041 /* Already created */
12045 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12046 result = type->data.klass;
12049 *handle_class = mono_defaults.typehandle_class;
12050 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12051 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12052 MonoMethodSignature *sig;
12055 if (helper->arguments)
12056 nargs = mono_array_length (helper->arguments);
12060 sig = mono_metadata_signature_alloc (image, nargs);
12061 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12062 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12064 if (helper->unmanaged_call_conv) { /* unmanaged */
12065 sig->call_convention = helper->unmanaged_call_conv - 1;
12066 sig->pinvoke = TRUE;
12067 } else if (helper->call_conv & 0x02) {
12068 sig->call_convention = MONO_CALL_VARARG;
12070 sig->call_convention = MONO_CALL_DEFAULT;
12073 sig->param_count = nargs;
12074 /* TODO: Copy type ? */
12075 sig->ret = helper->return_type->type;
12076 for (i = 0; i < nargs; ++i)
12077 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12080 *handle_class = NULL;
12081 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12082 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12083 /* Already created by the managed code */
12084 g_assert (method->mhandle);
12085 result = method->mhandle;
12086 *handle_class = mono_defaults.methodhandle_class;
12087 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12088 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12089 type = mono_class_inflate_generic_type (type, context);
12090 result = mono_class_from_mono_type (type);
12091 *handle_class = mono_defaults.typehandle_class;
12093 mono_metadata_free_type (type);
12094 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12095 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12096 type = mono_class_inflate_generic_type (type, context);
12097 result = mono_class_from_mono_type (type);
12098 *handle_class = mono_defaults.typehandle_class;
12100 mono_metadata_free_type (type);
12101 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12102 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12103 MonoClass *inflated;
12105 MonoClassField *field;
12107 if (is_sre_field_builder (mono_object_class (f->fb)))
12108 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12109 else if (is_sr_mono_field (mono_object_class (f->fb)))
12110 field = ((MonoReflectionField*)f->fb)->field;
12112 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)));
12114 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12115 inflated = mono_class_from_mono_type (type);
12117 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12118 ensure_complete_type (field->parent);
12120 mono_metadata_free_type (type);
12121 *handle_class = mono_defaults.fieldhandle_class;
12122 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12123 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12124 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12125 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12126 MonoMethod *method;
12128 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12129 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12130 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12131 method = ((MonoReflectionMethod *)c->cb)->method;
12133 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)));
12135 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12136 *handle_class = mono_defaults.methodhandle_class;
12137 mono_metadata_free_type (type);
12138 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12139 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12140 if (m->method_args) {
12141 result = mono_reflection_method_on_tb_inst_get_handle (m);
12143 result = mono_class_inflate_generic_method (result, context);
12145 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12146 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12147 MonoMethod *method;
12149 if (is_sre_method_builder (mono_object_class (m->mb)))
12150 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12151 else if (is_sr_mono_method (mono_object_class (m->mb)))
12152 method = ((MonoReflectionMethod *)m->mb)->method;
12154 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)));
12156 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12157 mono_metadata_free_type (type);
12159 *handle_class = mono_defaults.methodhandle_class;
12160 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12161 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12164 MonoMethod *method;
12168 mtype = mono_reflection_type_get_handle (m->parent);
12169 klass = mono_class_from_mono_type (mtype);
12171 /* Find the method */
12173 name = mono_string_to_utf8 (m->name);
12175 while ((method = mono_class_get_methods (klass, &iter))) {
12176 if (!strcmp (method->name, name))
12183 // FIXME: Check parameters/return value etc. match
12186 *handle_class = mono_defaults.methodhandle_class;
12187 } else if (is_sre_array (mono_object_get_class(obj)) ||
12188 is_sre_byref (mono_object_get_class(obj)) ||
12189 is_sre_pointer (mono_object_get_class(obj))) {
12190 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12191 MonoType *type = mono_reflection_type_get_handle (ref_type);
12194 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12195 result = mono_class_from_mono_type (inflated);
12196 mono_metadata_free_type (inflated);
12198 result = mono_class_from_mono_type (type);
12200 *handle_class = mono_defaults.typehandle_class;
12202 g_print ("%s\n", obj->vtable->klass->name);
12203 g_assert_not_reached ();
12208 #else /* DISABLE_REFLECTION_EMIT */
12211 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12213 g_assert_not_reached ();
12218 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12220 g_assert_not_reached ();
12224 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12226 g_assert_not_reached ();
12230 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12232 g_assert_not_reached ();
12236 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12238 g_assert_not_reached ();
12242 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12244 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12248 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12250 g_assert_not_reached ();
12254 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12256 g_assert_not_reached ();
12259 MonoReflectionModule *
12260 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12262 g_assert_not_reached ();
12267 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12269 g_assert_not_reached ();
12274 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12276 g_assert_not_reached ();
12281 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12282 gboolean create_open_instance, gboolean register_token)
12284 g_assert_not_reached ();
12289 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12294 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12296 g_assert_not_reached ();
12300 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12303 *num_overrides = 0;
12306 MonoReflectionEvent *
12307 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12309 g_assert_not_reached ();
12313 MonoReflectionType*
12314 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12316 g_assert_not_reached ();
12321 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12323 g_assert_not_reached ();
12327 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12329 g_assert_not_reached ();
12334 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12336 g_assert_not_reached ();
12341 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12346 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12352 mono_reflection_type_get_handle (MonoReflectionType* ref)
12360 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12362 g_assert_not_reached ();
12365 #endif /* DISABLE_REFLECTION_EMIT */
12367 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12368 const static guint32 declsec_flags_map[] = {
12369 0x00000000, /* empty */
12370 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12371 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12372 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12373 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12374 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12375 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12376 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12377 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12378 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12379 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12380 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12381 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12382 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12383 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12384 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12385 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12386 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12387 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12391 * Returns flags that includes all available security action associated to the handle.
12392 * @token: metadata token (either for a class or a method)
12393 * @image: image where resides the metadata.
12396 mono_declsec_get_flags (MonoImage *image, guint32 token)
12398 int index = mono_metadata_declsec_from_index (image, token);
12399 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12400 guint32 result = 0;
12404 /* HasSecurity can be present for other, not specially encoded, attributes,
12405 e.g. SuppressUnmanagedCodeSecurityAttribute */
12409 for (i = index; i < t->rows; i++) {
12410 guint32 cols [MONO_DECL_SECURITY_SIZE];
12412 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12413 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12416 action = cols [MONO_DECL_SECURITY_ACTION];
12417 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12418 result |= declsec_flags_map [action];
12420 g_assert_not_reached ();
12427 * Get the security actions (in the form of flags) associated with the specified method.
12429 * @method: The method for which we want the declarative security flags.
12430 * Return the declarative security flags for the method (only).
12432 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12433 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12436 mono_declsec_flags_from_method (MonoMethod *method)
12438 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12439 /* FIXME: No cache (for the moment) */
12440 guint32 idx = mono_method_get_index (method);
12441 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12442 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12443 return mono_declsec_get_flags (method->klass->image, idx);
12449 * Get the security actions (in the form of flags) associated with the specified class.
12451 * @klass: The class for which we want the declarative security flags.
12452 * Return the declarative security flags for the class.
12454 * Note: We cache the flags inside the MonoClass structure as this will get
12455 * called very often (at least for each method).
12458 mono_declsec_flags_from_class (MonoClass *klass)
12460 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12461 if (!klass->ext || !klass->ext->declsec_flags) {
12464 idx = mono_metadata_token_index (klass->type_token);
12465 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12466 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12467 mono_loader_lock ();
12468 mono_class_alloc_ext (klass);
12469 mono_loader_unlock ();
12470 /* we cache the flags on classes */
12471 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12473 return klass->ext->declsec_flags;
12479 * Get the security actions (in the form of flags) associated with the specified assembly.
12481 * @assembly: The assembly for which we want the declarative security flags.
12482 * Return the declarative security flags for the assembly.
12485 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12487 guint32 idx = 1; /* there is only one assembly */
12488 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12489 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12490 return mono_declsec_get_flags (assembly->image, idx);
12495 * Fill actions for the specific index (which may either be an encoded class token or
12496 * an encoded method token) from the metadata image.
12497 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12500 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12501 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12503 MonoBoolean result = FALSE;
12505 guint32 cols [MONO_DECL_SECURITY_SIZE];
12506 int index = mono_metadata_declsec_from_index (image, token);
12509 t = &image->tables [MONO_TABLE_DECLSECURITY];
12510 for (i = index; i < t->rows; i++) {
12511 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12513 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12516 /* if present only replace (class) permissions with method permissions */
12517 /* if empty accept either class or method permissions */
12518 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12519 if (!actions->demand.blob) {
12520 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12521 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12522 actions->demand.blob = (char*) (blob + 2);
12523 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12526 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12527 if (!actions->noncasdemand.blob) {
12528 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12529 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12530 actions->noncasdemand.blob = (char*) (blob + 2);
12531 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12534 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12535 if (!actions->demandchoice.blob) {
12536 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12537 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12538 actions->demandchoice.blob = (char*) (blob + 2);
12539 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12549 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12550 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12552 guint32 idx = mono_metadata_token_index (klass->type_token);
12553 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12554 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12555 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12559 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12560 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12562 guint32 idx = mono_method_get_index (method);
12563 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12564 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12565 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12569 * Collect all actions (that requires to generate code in mini) assigned for
12570 * the specified method.
12571 * Note: Don't use the content of actions if the function return FALSE.
12574 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12576 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12577 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12578 MonoBoolean result = FALSE;
12581 /* quick exit if no declarative security is present in the metadata */
12582 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12585 /* we want the original as the wrapper is "free" of the security informations */
12586 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12587 method = mono_marshal_method_from_wrapper (method);
12592 /* First we look for method-level attributes */
12593 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12594 mono_class_init (method->klass);
12595 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12597 result = mono_declsec_get_method_demands_params (method, demands,
12598 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12601 /* Here we use (or create) the class declarative cache to look for demands */
12602 flags = mono_declsec_flags_from_class (method->klass);
12603 if (flags & mask) {
12605 mono_class_init (method->klass);
12606 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12608 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12609 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12612 /* The boolean return value is used as a shortcut in case nothing needs to
12613 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12619 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12621 * Note: Don't use the content of actions if the function return FALSE.
12624 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12626 MonoBoolean result = FALSE;
12629 /* quick exit if no declarative security is present in the metadata */
12630 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12633 /* we want the original as the wrapper is "free" of the security informations */
12634 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12635 method = mono_marshal_method_from_wrapper (method);
12640 /* results are independant - zeroize both */
12641 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12642 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12644 /* First we look for method-level attributes */
12645 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12646 mono_class_init (method->klass);
12648 result = mono_declsec_get_method_demands_params (method, cmethod,
12649 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12652 /* Here we use (or create) the class declarative cache to look for demands */
12653 flags = mono_declsec_flags_from_class (method->klass);
12654 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12655 mono_class_init (method->klass);
12657 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12658 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12665 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12667 * @klass The inherited class - this is the class that provides the security check (attributes)
12669 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12671 * Note: Don't use the content of actions if the function return FALSE.
12674 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12676 MonoBoolean result = FALSE;
12679 /* quick exit if no declarative security is present in the metadata */
12680 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12683 /* Here we use (or create) the class declarative cache to look for demands */
12684 flags = mono_declsec_flags_from_class (klass);
12685 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12686 mono_class_init (klass);
12687 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12689 result |= mono_declsec_get_class_demands_params (klass, demands,
12690 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12697 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12699 * Note: Don't use the content of actions if the function return FALSE.
12702 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12704 /* quick exit if no declarative security is present in the metadata */
12705 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12708 /* we want the original as the wrapper is "free" of the security informations */
12709 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12710 method = mono_marshal_method_from_wrapper (method);
12715 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12716 mono_class_init (method->klass);
12717 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12719 return mono_declsec_get_method_demands_params (method, demands,
12720 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12727 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12729 guint32 cols [MONO_DECL_SECURITY_SIZE];
12733 int index = mono_metadata_declsec_from_index (image, token);
12737 t = &image->tables [MONO_TABLE_DECLSECURITY];
12738 for (i = index; i < t->rows; i++) {
12739 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12741 /* shortcut - index are ordered */
12742 if (token != cols [MONO_DECL_SECURITY_PARENT])
12745 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12746 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12747 entry->blob = (char*) (metadata + 2);
12748 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12757 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12759 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12760 guint32 idx = mono_method_get_index (method);
12761 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12762 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12763 return get_declsec_action (method->klass->image, idx, action, entry);
12769 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12772 guint32 flags = mono_declsec_flags_from_class (klass);
12773 if (declsec_flags_map [action] & flags) {
12774 guint32 idx = mono_metadata_token_index (klass->type_token);
12775 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12776 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12777 return get_declsec_action (klass->image, idx, action, entry);
12783 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12785 guint32 idx = 1; /* there is only one assembly */
12786 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12787 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12789 return get_declsec_action (assembly->image, idx, action, entry);
12793 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12795 MonoObject *res, *exc;
12797 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12798 static MonoMethod *method = NULL;
12800 if (!System_Reflection_Emit_TypeBuilder) {
12801 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12802 g_assert (System_Reflection_Emit_TypeBuilder);
12804 if (method == NULL) {
12805 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12810 * The result of mono_type_get_object () might be a System.MonoType but we
12811 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12813 g_assert (mono_class_get_ref_info (klass));
12814 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12816 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12818 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12822 return *(MonoBoolean*)mono_object_unbox (res);
12826 * mono_reflection_type_get_type:
12827 * @reftype: the System.Type object
12829 * Returns the MonoType* associated with the C# System.Type object @reftype.
12832 mono_reflection_type_get_type (MonoReflectionType *reftype)
12834 g_assert (reftype);
12836 return mono_reflection_type_get_handle (reftype);
12840 * mono_reflection_assembly_get_assembly:
12841 * @refassembly: the System.Reflection.Assembly object
12843 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
12846 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
12848 g_assert (refassembly);
12850 return refassembly->assembly;