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 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;
2779 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2782 if (is_sre_field_builder (mono_object_class (f->fb))) {
2783 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2784 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785 klass = mono_class_from_mono_type (type);
2786 gclass = type->data.generic_class;
2787 g_assert (gclass->is_dynamic);
2789 name = mono_string_to_utf8 (fb->name);
2790 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2791 field_encode_signature (assembly, fb));
2793 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2795 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2797 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2798 klass = mono_class_from_mono_type (type);
2800 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2801 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2803 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2804 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2807 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2812 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2816 MonoGenericClass *gclass;
2819 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2821 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2825 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2826 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2827 ReflectionMethodBuilder rmb;
2830 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2831 klass = mono_class_from_mono_type (type);
2833 gclass = type->data.generic_class;
2834 g_assert (gclass->is_dynamic);
2836 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2838 name = mono_string_to_utf8 (rmb.name);
2840 sig = method_builder_encode_signature (assembly, &rmb);
2842 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2844 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2845 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2847 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2848 klass = mono_class_from_mono_type (type);
2850 sig = method_encode_signature (assembly, mono_method_signature (mm));
2851 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2853 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2854 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2858 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2863 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2867 MonoGenericContext tmp_context;
2868 MonoType **type_argv;
2869 MonoGenericInst *ginst;
2870 MonoMethod *method, *inflated;
2873 init_type_builder_generics ((MonoObject*)m->inst);
2875 method = inflate_method (m->inst, (MonoObject*)m->mb);
2877 klass = method->klass;
2879 if (m->method_args == NULL)
2882 if (method->is_inflated)
2883 method = ((MonoMethodInflated *) method)->declaring;
2885 count = mono_array_length (m->method_args);
2887 type_argv = g_new0 (MonoType *, count);
2888 for (i = 0; i < count; i++) {
2889 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2890 type_argv [i] = mono_reflection_type_get_handle (garg);
2892 ginst = mono_metadata_get_generic_inst (count, type_argv);
2895 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2896 tmp_context.method_inst = ginst;
2898 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
2899 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2904 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2906 guint32 sig, token = 0;
2910 if (m->method_args) {
2911 MonoMethod *inflated;
2913 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2914 if (create_methodspec)
2915 token = mono_image_get_methodspec_token (assembly, inflated);
2917 token = mono_image_get_inflated_method_token (assembly, inflated);
2921 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2925 if (is_sre_method_builder (mono_object_class (m->mb))) {
2926 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2927 MonoGenericClass *gclass;
2928 ReflectionMethodBuilder rmb;
2931 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2932 klass = mono_class_from_mono_type (type);
2933 gclass = type->data.generic_class;
2934 g_assert (gclass->is_dynamic);
2936 reflection_methodbuilder_from_method_builder (&rmb, mb);
2938 name = mono_string_to_utf8 (rmb.name);
2940 sig = method_builder_encode_signature (assembly, &rmb);
2942 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2944 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2945 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2947 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2948 klass = mono_class_from_mono_type (type);
2950 sig = method_encode_signature (assembly, mono_method_signature (mm));
2951 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2953 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2954 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2957 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2962 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2966 guint32 nparams = context->method_inst->type_argc;
2969 if (!assembly->save)
2972 sigbuffer_init (&buf, 32);
2974 * FIXME: vararg, explicit_this, differenc call_conv values...
2976 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2977 sigbuffer_add_value (&buf, nparams);
2979 for (i = 0; i < nparams; i++)
2980 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2982 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2983 sigbuffer_free (&buf);
2988 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2990 MonoDynamicTable *table;
2992 guint32 token, mtoken = 0, sig;
2993 MonoMethodInflated *imethod;
2994 MonoMethod *declaring;
2996 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2998 g_assert (method->is_inflated);
2999 imethod = (MonoMethodInflated *) method;
3000 declaring = imethod->declaring;
3002 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3003 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3005 if (!mono_method_signature (declaring)->generic_param_count)
3008 switch (mono_metadata_token_table (mtoken)) {
3009 case MONO_TABLE_MEMBERREF:
3010 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3012 case MONO_TABLE_METHOD:
3013 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3016 g_assert_not_reached ();
3019 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3021 if (assembly->save) {
3022 alloc_table (table, table->rows + 1);
3023 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3024 values [MONO_METHODSPEC_METHOD] = mtoken;
3025 values [MONO_METHODSPEC_SIGNATURE] = sig;
3028 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3035 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3037 MonoMethodInflated *imethod;
3040 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3044 g_assert (method->is_inflated);
3045 imethod = (MonoMethodInflated *) method;
3047 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3048 token = method_encode_methodspec (assembly, method);
3050 guint32 sig = method_encode_signature (
3051 assembly, mono_method_signature (imethod->declaring));
3052 token = mono_image_get_memberref_token (
3053 assembly, &method->klass->byval_arg, method->name, sig);
3056 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3061 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3063 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3066 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3067 token = mono_image_get_memberref_token (
3068 assembly, &m->klass->byval_arg, m->name, sig);
3074 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3076 MonoDynamicTable *table;
3085 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3086 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3087 * Because of this, we must not insert it into the `typeref' hash table.
3089 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3090 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3094 sigbuffer_init (&buf, 32);
3096 g_assert (tb->generic_params);
3097 klass = mono_class_from_mono_type (type);
3099 if (tb->generic_container)
3100 mono_reflection_create_generic_class (tb);
3102 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3103 g_assert (klass->generic_container);
3104 sigbuffer_add_value (&buf, klass->byval_arg.type);
3105 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3107 count = mono_array_length (tb->generic_params);
3108 sigbuffer_add_value (&buf, count);
3109 for (i = 0; i < count; i++) {
3110 MonoReflectionGenericParam *gparam;
3112 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3114 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3117 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3119 if (assembly->save) {
3120 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3121 alloc_table (table, table->rows + 1);
3122 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3123 values [MONO_TYPESPEC_SIGNATURE] = token;
3125 sigbuffer_free (&buf);
3127 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3128 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3134 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3137 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3139 int i, count, len, pos;
3144 count += mono_array_length (modreq);
3146 count += mono_array_length (modopt);
3149 return mono_metadata_type_dup (NULL, type);
3151 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3153 memcpy (t, type, MONO_SIZEOF_TYPE);
3155 t->num_mods = count;
3158 for (i = 0; i < mono_array_length (modreq); ++i) {
3159 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3160 t->modifiers [pos].required = 1;
3161 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3166 for (i = 0; i < mono_array_length (modopt); ++i) {
3167 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3168 t->modifiers [pos].required = 0;
3169 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3178 init_type_builder_generics (MonoObject *type)
3180 MonoReflectionTypeBuilder *tb;
3182 if (!is_sre_type_builder(mono_object_class (type)))
3184 tb = (MonoReflectionTypeBuilder *)type;
3186 if (tb && tb->generic_container)
3187 mono_reflection_create_generic_class (tb);
3191 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3193 MonoDynamicTable *table;
3194 MonoType *custom = NULL, *type;
3196 guint32 token, pclass, parent, sig;
3199 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3203 /* FIXME: is this call necessary? */
3204 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3205 name = mono_string_to_utf8 (fb->name);
3207 /*FIXME this is one more layer of ugliness due how types are created.*/
3208 init_type_builder_generics (fb->type);
3210 /* fb->type does not include the custom modifiers */
3211 /* FIXME: We should do this in one place when a fieldbuilder is created */
3212 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3213 if (fb->modreq || fb->modopt)
3214 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3216 sig = fieldref_encode_signature (assembly, NULL, type);
3219 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3220 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3222 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3223 parent >>= MONO_TYPEDEFORREF_BITS;
3225 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3227 if (assembly->save) {
3228 alloc_table (table, table->rows + 1);
3229 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3230 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3231 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3232 values [MONO_MEMBERREF_SIGNATURE] = sig;
3235 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3237 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3243 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3249 if (!assembly->save)
3252 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3253 g_assert (helper->type == 2);
3255 if (helper->arguments)
3256 nargs = mono_array_length (helper->arguments);
3260 sigbuffer_init (&buf, 32);
3262 /* Encode calling convention */
3263 /* Change Any to Standard */
3264 if ((helper->call_conv & 0x03) == 0x03)
3265 helper->call_conv = 0x01;
3266 /* explicit_this implies has_this */
3267 if (helper->call_conv & 0x40)
3268 helper->call_conv &= 0x20;
3270 if (helper->call_conv == 0) { /* Unmanaged */
3271 idx = helper->unmanaged_call_conv - 1;
3274 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3275 if (helper->call_conv & 0x02) /* varargs */
3279 sigbuffer_add_byte (&buf, idx);
3280 sigbuffer_add_value (&buf, nargs);
3281 encode_reflection_type (assembly, helper->return_type, &buf);
3282 for (i = 0; i < nargs; ++i) {
3283 MonoArray *modreqs = NULL;
3284 MonoArray *modopts = NULL;
3285 MonoReflectionType *pt;
3287 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3288 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3289 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3290 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3292 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3293 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3294 encode_reflection_type (assembly, pt, &buf);
3296 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3297 sigbuffer_free (&buf);
3303 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3306 MonoDynamicTable *table;
3309 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3310 idx = table->next_idx ++;
3312 alloc_table (table, table->rows);
3313 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3315 values [MONO_STAND_ALONE_SIGNATURE] =
3316 mono_reflection_encode_sighelper (assembly, helper);
3322 reflection_cc_to_file (int call_conv) {
3323 switch (call_conv & 0x3) {
3325 case 1: return MONO_CALL_DEFAULT;
3326 case 2: return MONO_CALL_VARARG;
3328 g_assert_not_reached ();
3332 #endif /* !DISABLE_REFLECTION_EMIT */
3336 MonoMethodSignature *sig;
3341 #ifndef DISABLE_REFLECTION_EMIT
3343 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3348 MonoMethodSignature *sig;
3352 name = mono_string_to_utf8 (m->name);
3353 nparams = mono_array_length (m->parameters);
3354 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3356 sig->sentinelpos = -1;
3357 sig->call_convention = reflection_cc_to_file (m->call_conv);
3358 sig->param_count = nparams;
3359 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3360 mtype = mono_reflection_type_get_handle (m->parent);
3361 for (i = 0; i < nparams; ++i)
3362 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3364 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3366 if (strcmp (name, am->name) == 0 &&
3367 mono_metadata_type_equal (am->parent, mtype) &&
3368 mono_metadata_signature_equal (am->sig, sig)) {
3371 m->table_idx = am->token & 0xffffff;
3375 am = g_new0 (ArrayMethod, 1);
3379 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3380 method_encode_signature (assembly, sig));
3381 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3382 m->table_idx = am->token & 0xffffff;
3387 * Insert into the metadata tables all the info about the TypeBuilder tb.
3388 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3391 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3393 MonoDynamicTable *table;
3395 int i, is_object = 0, is_system = 0;
3398 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3399 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3400 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3401 n = mono_string_to_utf8 (tb->name);
3402 if (strcmp (n, "Object") == 0)
3404 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3406 n = mono_string_to_utf8 (tb->nspace);
3407 if (strcmp (n, "System") == 0)
3409 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3411 if (tb->parent && !(is_system && is_object) &&
3412 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3413 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3415 values [MONO_TYPEDEF_EXTENDS] = 0;
3417 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3418 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3421 * if we have explicitlayout or sequentiallayouts, output data in the
3422 * ClassLayout table.
3424 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3425 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3426 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3428 alloc_table (table, table->rows);
3429 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3430 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3431 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3432 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3435 /* handle interfaces */
3436 if (tb->interfaces) {
3437 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3439 table->rows += mono_array_length (tb->interfaces);
3440 alloc_table (table, table->rows);
3441 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3442 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3443 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3444 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3445 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3446 values += MONO_INTERFACEIMPL_SIZE;
3452 table = &assembly->tables [MONO_TABLE_FIELD];
3453 table->rows += tb->num_fields;
3454 alloc_table (table, table->rows);
3455 for (i = 0; i < tb->num_fields; ++i)
3456 mono_image_get_field_info (
3457 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3460 /* handle constructors */
3462 table = &assembly->tables [MONO_TABLE_METHOD];
3463 table->rows += mono_array_length (tb->ctors);
3464 alloc_table (table, table->rows);
3465 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3466 mono_image_get_ctor_info (domain,
3467 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3470 /* handle methods */
3472 table = &assembly->tables [MONO_TABLE_METHOD];
3473 table->rows += tb->num_methods;
3474 alloc_table (table, table->rows);
3475 for (i = 0; i < tb->num_methods; ++i)
3476 mono_image_get_method_info (
3477 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3480 /* Do the same with properties etc.. */
3481 if (tb->events && mono_array_length (tb->events)) {
3482 table = &assembly->tables [MONO_TABLE_EVENT];
3483 table->rows += mono_array_length (tb->events);
3484 alloc_table (table, table->rows);
3485 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3487 alloc_table (table, table->rows);
3488 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3489 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3490 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3491 for (i = 0; i < mono_array_length (tb->events); ++i)
3492 mono_image_get_event_info (
3493 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3495 if (tb->properties && mono_array_length (tb->properties)) {
3496 table = &assembly->tables [MONO_TABLE_PROPERTY];
3497 table->rows += mono_array_length (tb->properties);
3498 alloc_table (table, table->rows);
3499 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3501 alloc_table (table, table->rows);
3502 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3503 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3504 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3505 for (i = 0; i < mono_array_length (tb->properties); ++i)
3506 mono_image_get_property_info (
3507 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3510 /* handle generic parameters */
3511 if (tb->generic_params) {
3512 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3513 table->rows += mono_array_length (tb->generic_params);
3514 alloc_table (table, table->rows);
3515 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3516 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3518 mono_image_get_generic_param_info (
3519 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3523 mono_image_add_decl_security (assembly,
3524 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3527 MonoDynamicTable *ntable;
3529 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3530 ntable->rows += mono_array_length (tb->subtypes);
3531 alloc_table (ntable, ntable->rows);
3532 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3534 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3535 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3537 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3538 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3539 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3540 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3541 mono_string_to_utf8 (tb->name), tb->table_idx,
3542 ntable->next_idx, ntable->rows);*/
3543 values += MONO_NESTED_CLASS_SIZE;
3551 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3555 mono_ptr_array_append (*types, type);
3557 if (!type->subtypes)
3560 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3561 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3562 collect_types (types, subtype);
3567 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3569 if ((*type1)->table_idx < (*type2)->table_idx)
3572 if ((*type1)->table_idx > (*type2)->table_idx)
3579 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3584 for (i = 0; i < mono_array_length (pinfo); ++i) {
3585 MonoReflectionParamBuilder *pb;
3586 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3589 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3594 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3597 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3599 for (i = 0; i < tb->num_fields; ++i) {
3600 MonoReflectionFieldBuilder* fb;
3601 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3602 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3606 for (i = 0; i < mono_array_length (tb->events); ++i) {
3607 MonoReflectionEventBuilder* eb;
3608 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3609 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3612 if (tb->properties) {
3613 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3614 MonoReflectionPropertyBuilder* pb;
3615 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3616 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3620 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3621 MonoReflectionCtorBuilder* cb;
3622 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3623 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3624 params_add_cattrs (assembly, cb->pinfo);
3629 for (i = 0; i < tb->num_methods; ++i) {
3630 MonoReflectionMethodBuilder* mb;
3631 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3632 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3633 params_add_cattrs (assembly, mb->pinfo);
3638 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3639 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3644 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3648 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3650 if (moduleb->global_methods) {
3651 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3652 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3653 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3654 params_add_cattrs (assembly, mb->pinfo);
3658 if (moduleb->global_fields) {
3659 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3660 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3661 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3665 if (moduleb->types) {
3666 for (i = 0; i < moduleb->num_types; ++i)
3667 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3672 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3674 MonoDynamicTable *table;
3678 char *b = blob_size;
3681 table = &assembly->tables [MONO_TABLE_FILE];
3683 alloc_table (table, table->rows);
3684 values = table->values + table->next_idx * MONO_FILE_SIZE;
3685 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3686 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3687 if (image_is_dynamic (module->image)) {
3688 /* This depends on the fact that the main module is emitted last */
3689 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3690 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3693 path = g_strdup (module->image->name);
3695 mono_sha1_get_digest_from_file (path, hash);
3698 mono_metadata_encode_value (20, b, &b);
3699 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3700 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3705 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3707 MonoDynamicTable *table;
3710 table = &assembly->tables [MONO_TABLE_MODULE];
3711 mb->table_idx = table->next_idx ++;
3712 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3713 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3716 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3717 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3718 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3719 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3723 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3724 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3726 MonoDynamicTable *table;
3730 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3731 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3734 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3736 alloc_table (table, table->rows);
3737 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3739 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3740 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3741 if (klass->nested_in)
3742 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3744 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3745 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3746 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3748 res = table->next_idx;
3752 /* Emit nested types */
3753 if (klass->ext && klass->ext->nested_classes) {
3756 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3757 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3764 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3765 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3770 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3772 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3774 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3775 parent_index, assembly);
3779 * We need to do this ourselves since klass->nested_classes is not set up.
3782 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3783 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3788 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3789 guint32 module_index, MonoDynamicImage *assembly)
3791 MonoImage *image = module->image;
3795 t = &image->tables [MONO_TABLE_TYPEDEF];
3797 for (i = 0; i < t->rows; ++i) {
3799 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3800 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3802 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3803 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3808 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3810 MonoDynamicTable *table;
3812 guint32 scope, scope_idx, impl, current_idx;
3813 gboolean forwarder = TRUE;
3814 gpointer iter = NULL;
3817 if (klass->nested_in) {
3818 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3821 scope = resolution_scope_from_image (assembly, klass->image);
3822 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
3823 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
3824 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3827 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3830 alloc_table (table, table->rows);
3831 current_idx = table->next_idx;
3832 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3834 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3835 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3836 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3837 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3838 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3842 while ((nested = mono_class_get_nested_types (klass, &iter)))
3843 add_exported_type (assemblyb, assembly, nested, current_idx);
3847 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3852 if (!assemblyb->type_forwarders)
3855 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3856 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3861 type = mono_reflection_type_get_handle (t);
3864 klass = mono_class_from_mono_type (type);
3866 add_exported_type (assemblyb, assembly, klass, 0);
3870 #define align_pointer(base,p)\
3872 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3874 (p) += 4 - (__diff & 3);\
3878 compare_constants (const void *a, const void *b)
3880 const guint32 *a_values = a;
3881 const guint32 *b_values = b;
3882 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3886 compare_semantics (const void *a, const void *b)
3888 const guint32 *a_values = a;
3889 const guint32 *b_values = b;
3890 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3893 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3897 compare_custom_attrs (const void *a, const void *b)
3899 const guint32 *a_values = a;
3900 const guint32 *b_values = b;
3902 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3906 compare_field_marshal (const void *a, const void *b)
3908 const guint32 *a_values = a;
3909 const guint32 *b_values = b;
3911 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3915 compare_nested (const void *a, const void *b)
3917 const guint32 *a_values = a;
3918 const guint32 *b_values = b;
3920 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3924 compare_genericparam (const void *a, const void *b)
3926 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3927 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3929 if ((*b_entry)->owner == (*a_entry)->owner)
3931 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3932 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3934 return (*a_entry)->owner - (*b_entry)->owner;
3938 compare_declsecurity_attrs (const void *a, const void *b)
3940 const guint32 *a_values = a;
3941 const guint32 *b_values = b;
3943 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3947 compare_interface_impl (const void *a, const void *b)
3949 const guint32 *a_values = a;
3950 const guint32 *b_values = b;
3952 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3956 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3960 pad_heap (MonoDynamicStream *sh)
3962 if (sh->index & 3) {
3963 int sz = 4 - (sh->index & 3);
3964 memset (sh->data + sh->index, 0, sz);
3971 MonoDynamicStream *stream;
3975 * build_compressed_metadata() fills in the blob of data that represents the
3976 * raw metadata as it will be saved in the PE file. The five streams are output
3977 * and the metadata tables are comnpressed from the guint32 array representation,
3978 * to the compressed on-disk format.
3981 build_compressed_metadata (MonoDynamicImage *assembly)
3983 MonoDynamicTable *table;
3985 guint64 valid_mask = 0;
3986 guint64 sorted_mask;
3987 guint32 heapt_size = 0;
3988 guint32 meta_size = 256; /* allow for header and other stuff */
3989 guint32 table_offset;
3990 guint32 ntables = 0;
3996 struct StreamDesc stream_desc [5];
3998 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3999 for (i = 0; i < assembly->gen_params->len; i++){
4000 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4001 write_generic_param_entry (assembly, entry);
4004 stream_desc [0].name = "#~";
4005 stream_desc [0].stream = &assembly->tstream;
4006 stream_desc [1].name = "#Strings";
4007 stream_desc [1].stream = &assembly->sheap;
4008 stream_desc [2].name = "#US";
4009 stream_desc [2].stream = &assembly->us;
4010 stream_desc [3].name = "#Blob";
4011 stream_desc [3].stream = &assembly->blob;
4012 stream_desc [4].name = "#GUID";
4013 stream_desc [4].stream = &assembly->guid;
4015 /* tables that are sorted */
4016 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4017 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4018 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4019 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4020 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4021 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4022 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4024 /* Compute table sizes */
4025 /* the MonoImage has already been created in mono_image_basic_init() */
4026 meta = &assembly->image;
4028 /* sizes should be multiple of 4 */
4029 pad_heap (&assembly->blob);
4030 pad_heap (&assembly->guid);
4031 pad_heap (&assembly->sheap);
4032 pad_heap (&assembly->us);
4034 /* Setup the info used by compute_sizes () */
4035 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4036 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4037 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4039 meta_size += assembly->blob.index;
4040 meta_size += assembly->guid.index;
4041 meta_size += assembly->sheap.index;
4042 meta_size += assembly->us.index;
4044 for (i=0; i < MONO_TABLE_NUM; ++i)
4045 meta->tables [i].rows = assembly->tables [i].rows;
4047 for (i = 0; i < MONO_TABLE_NUM; i++){
4048 if (meta->tables [i].rows == 0)
4050 valid_mask |= (guint64)1 << i;
4052 meta->tables [i].row_size = mono_metadata_compute_size (
4053 meta, i, &meta->tables [i].size_bitfield);
4054 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4056 heapt_size += 24; /* #~ header size */
4057 heapt_size += ntables * 4;
4058 /* make multiple of 4 */
4061 meta_size += heapt_size;
4062 meta->raw_metadata = g_malloc0 (meta_size);
4063 p = (unsigned char*)meta->raw_metadata;
4064 /* the metadata signature */
4065 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4066 /* version numbers and 4 bytes reserved */
4067 int16val = (guint16*)p;
4068 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4069 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4071 /* version string */
4072 int32val = (guint32*)p;
4073 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4075 memcpy (p, meta->version, strlen (meta->version));
4076 p += GUINT32_FROM_LE (*int32val);
4077 align_pointer (meta->raw_metadata, p);
4078 int16val = (guint16*)p;
4079 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4080 *int16val = GUINT16_TO_LE (5); /* number of streams */
4084 * write the stream info.
4086 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4087 table_offset += 3; table_offset &= ~3;
4089 assembly->tstream.index = heapt_size;
4090 for (i = 0; i < 5; ++i) {
4091 int32val = (guint32*)p;
4092 stream_desc [i].stream->offset = table_offset;
4093 *int32val++ = GUINT32_TO_LE (table_offset);
4094 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4095 table_offset += GUINT32_FROM_LE (*int32val);
4096 table_offset += 3; table_offset &= ~3;
4098 strcpy ((char*)p, stream_desc [i].name);
4099 p += strlen (stream_desc [i].name) + 1;
4100 align_pointer (meta->raw_metadata, p);
4103 * now copy the data, the table stream header and contents goes first.
4105 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4106 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4107 int32val = (guint32*)p;
4108 *int32val = GUINT32_TO_LE (0); /* reserved */
4111 *p++ = 2; /* version */
4114 if (meta->idx_string_wide)
4116 if (meta->idx_guid_wide)
4118 if (meta->idx_blob_wide)
4121 *p++ = 1; /* reserved */
4122 int64val = (guint64*)p;
4123 *int64val++ = GUINT64_TO_LE (valid_mask);
4124 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4126 int32val = (guint32*)p;
4127 for (i = 0; i < MONO_TABLE_NUM; i++){
4128 if (meta->tables [i].rows == 0)
4130 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4132 p = (unsigned char*)int32val;
4134 /* sort the tables that still need sorting */
4135 table = &assembly->tables [MONO_TABLE_CONSTANT];
4137 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4138 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4140 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4141 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4143 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4144 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4146 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4147 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4149 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4150 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4151 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4153 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4154 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4156 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4158 /* compress the tables */
4159 for (i = 0; i < MONO_TABLE_NUM; i++){
4162 guint32 bitfield = meta->tables [i].size_bitfield;
4163 if (!meta->tables [i].rows)
4165 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4166 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4167 meta->tables [i].base = (char*)p;
4168 for (row = 1; row <= meta->tables [i].rows; ++row) {
4169 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4170 for (col = 0; col < assembly->tables [i].columns; ++col) {
4171 switch (mono_metadata_table_size (bitfield, col)) {
4173 *p++ = values [col];
4176 *p++ = values [col] & 0xff;
4177 *p++ = (values [col] >> 8) & 0xff;
4180 *p++ = values [col] & 0xff;
4181 *p++ = (values [col] >> 8) & 0xff;
4182 *p++ = (values [col] >> 16) & 0xff;
4183 *p++ = (values [col] >> 24) & 0xff;
4186 g_assert_not_reached ();
4190 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4193 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4194 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4195 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4196 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4197 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4199 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4203 * Some tables in metadata need to be sorted according to some criteria, but
4204 * when methods and fields are first created with reflection, they may be assigned a token
4205 * that doesn't correspond to the final token they will get assigned after the sorting.
4206 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4207 * with the reflection objects that represent them. Once all the tables are set up, the
4208 * reflection objects will contains the correct table index. fixup_method() will fixup the
4209 * tokens for the method with ILGenerator @ilgen.
4212 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4214 guint32 code_idx = GPOINTER_TO_UINT (value);
4215 MonoReflectionILTokenInfo *iltoken;
4216 MonoReflectionFieldBuilder *field;
4217 MonoReflectionCtorBuilder *ctor;
4218 MonoReflectionMethodBuilder *method;
4219 MonoReflectionTypeBuilder *tb;
4220 MonoReflectionArrayMethod *am;
4222 unsigned char *target;
4224 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4225 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4226 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4227 switch (target [3]) {
4228 case MONO_TABLE_FIELD:
4229 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4230 field = (MonoReflectionFieldBuilder *)iltoken->member;
4231 idx = field->table_idx;
4232 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4233 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4234 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4236 g_assert_not_reached ();
4239 case MONO_TABLE_METHOD:
4240 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4241 method = (MonoReflectionMethodBuilder *)iltoken->member;
4242 idx = method->table_idx;
4243 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4244 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4245 idx = ctor->table_idx;
4246 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4247 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4248 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4249 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4251 g_assert_not_reached ();
4254 case MONO_TABLE_TYPEDEF:
4255 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4256 g_assert_not_reached ();
4257 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4258 idx = tb->table_idx;
4260 case MONO_TABLE_MEMBERREF:
4261 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4262 am = (MonoReflectionArrayMethod*)iltoken->member;
4263 idx = am->table_idx;
4264 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4265 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4266 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4267 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4268 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4269 g_assert (m->klass->generic_class || m->klass->generic_container);
4271 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4273 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4274 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4275 g_assert (is_field_on_inst (f));
4277 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4278 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4280 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4282 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4284 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4287 g_assert_not_reached ();
4290 case MONO_TABLE_METHODSPEC:
4291 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4292 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4293 g_assert (mono_method_signature (m)->generic_param_count);
4295 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4297 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4300 g_assert_not_reached ();
4304 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4306 target [0] = idx & 0xff;
4307 target [1] = (idx >> 8) & 0xff;
4308 target [2] = (idx >> 16) & 0xff;
4315 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4316 * value is not known when the table is emitted.
4319 fixup_cattrs (MonoDynamicImage *assembly)
4321 MonoDynamicTable *table;
4323 guint32 type, i, idx, token;
4326 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4328 for (i = 0; i < table->rows; ++i) {
4329 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4331 type = values [MONO_CUSTOM_ATTR_TYPE];
4332 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4333 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4334 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4335 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4338 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4339 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4340 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4341 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4342 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4343 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4344 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4345 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4352 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4354 MonoDynamicTable *table;
4357 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4359 alloc_table (table, table->rows);
4360 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4361 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4362 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4363 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4364 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4369 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4371 MonoDynamicTable *table;
4375 char *b = blob_size;
4377 guint32 idx, offset;
4379 if (rsrc->filename) {
4380 name = mono_string_to_utf8 (rsrc->filename);
4381 sname = g_path_get_basename (name);
4383 table = &assembly->tables [MONO_TABLE_FILE];
4385 alloc_table (table, table->rows);
4386 values = table->values + table->next_idx * MONO_FILE_SIZE;
4387 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4388 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4391 mono_sha1_get_digest_from_file (name, hash);
4392 mono_metadata_encode_value (20, b, &b);
4393 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4394 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4396 idx = table->next_idx++;
4398 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4404 data = mono_array_addr (rsrc->data, char, 0);
4405 len = mono_array_length (rsrc->data);
4411 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4412 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4413 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4414 mono_image_add_stream_data (&assembly->resources, data, len);
4418 * The entry should be emitted into the MANIFESTRESOURCE table of
4419 * the main module, but that needs to reference the FILE table
4420 * which isn't emitted yet.
4427 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4431 set_version_from_string (MonoString *version, guint32 *values)
4433 gchar *ver, *p, *str;
4436 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4437 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4438 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4439 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4442 ver = str = mono_string_to_utf8 (version);
4443 for (i = 0; i < 4; ++i) {
4444 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4450 /* handle Revision and Build */
4460 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4464 char *b = blob_size;
4469 len = mono_array_length (pkey);
4470 mono_metadata_encode_value (len, b, &b);
4471 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4472 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4474 assembly->public_key = g_malloc (len);
4475 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4476 assembly->public_key_len = len;
4478 /* Special case: check for ECMA key (16 bytes) */
4479 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4480 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4481 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4482 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4483 /* minimum key size (in 2.0) is 384 bits */
4484 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4486 /* FIXME - verifier */
4487 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4488 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4490 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4496 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4498 MonoDynamicTable *table;
4499 MonoDynamicImage *assembly;
4500 MonoReflectionAssemblyBuilder *assemblyb;
4504 guint32 module_index;
4506 assemblyb = moduleb->assemblyb;
4507 assembly = moduleb->dynamic_image;
4508 domain = mono_object_domain (assemblyb);
4510 /* Emit ASSEMBLY table */
4511 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4512 alloc_table (table, 1);
4513 values = table->values + MONO_ASSEMBLY_SIZE;
4514 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4515 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4516 if (assemblyb->culture) {
4517 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4519 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4521 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4522 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4523 set_version_from_string (assemblyb->version, values);
4525 /* Emit FILE + EXPORTED_TYPE table */
4527 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4529 MonoReflectionModuleBuilder *file_module =
4530 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4531 if (file_module != moduleb) {
4532 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4534 if (file_module->types) {
4535 for (j = 0; j < file_module->num_types; ++j) {
4536 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4537 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4542 if (assemblyb->loaded_modules) {
4543 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4544 MonoReflectionModule *file_module =
4545 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4546 mono_image_fill_file_table (domain, file_module, assembly);
4548 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4551 if (assemblyb->type_forwarders)
4552 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4554 /* Emit MANIFESTRESOURCE table */
4556 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4558 MonoReflectionModuleBuilder *file_module =
4559 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4560 /* The table for the main module is emitted later */
4561 if (file_module != moduleb) {
4563 if (file_module->resources) {
4564 int len = mono_array_length (file_module->resources);
4565 for (j = 0; j < len; ++j) {
4566 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4567 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4574 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4577 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4578 * for the modulebuilder @moduleb.
4579 * At the end of the process, method and field tokens are fixed up and the
4580 * on-disk compressed metadata representation is created.
4583 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4585 MonoDynamicTable *table;
4586 MonoDynamicImage *assembly;
4587 MonoReflectionAssemblyBuilder *assemblyb;
4593 assemblyb = moduleb->assemblyb;
4594 assembly = moduleb->dynamic_image;
4595 domain = mono_object_domain (assemblyb);
4597 if (assembly->text_rva)
4600 assembly->text_rva = START_TEXT_RVA;
4602 if (moduleb->is_main) {
4603 mono_image_emit_manifest (moduleb);
4606 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4607 table->rows = 1; /* .<Module> */
4609 alloc_table (table, table->rows);
4611 * Set the first entry.
4613 values = table->values + table->columns;
4614 values [MONO_TYPEDEF_FLAGS] = 0;
4615 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4616 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4617 values [MONO_TYPEDEF_EXTENDS] = 0;
4618 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4619 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4622 * handle global methods
4623 * FIXME: test what to do when global methods are defined in multiple modules.
4625 if (moduleb->global_methods) {
4626 table = &assembly->tables [MONO_TABLE_METHOD];
4627 table->rows += mono_array_length (moduleb->global_methods);
4628 alloc_table (table, table->rows);
4629 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4630 mono_image_get_method_info (
4631 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4633 if (moduleb->global_fields) {
4634 table = &assembly->tables [MONO_TABLE_FIELD];
4635 table->rows += mono_array_length (moduleb->global_fields);
4636 alloc_table (table, table->rows);
4637 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4638 mono_image_get_field_info (
4639 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4642 table = &assembly->tables [MONO_TABLE_MODULE];
4643 alloc_table (table, 1);
4644 mono_image_fill_module_table (domain, moduleb, assembly);
4646 /* Collect all types into a list sorted by their table_idx */
4647 mono_ptr_array_init (types, moduleb->num_types);
4650 for (i = 0; i < moduleb->num_types; ++i) {
4651 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4652 collect_types (&types, type);
4655 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4656 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4657 table->rows += mono_ptr_array_size (types);
4658 alloc_table (table, table->rows);
4661 * Emit type names + namespaces at one place inside the string heap,
4662 * so load_class_names () needs to touch fewer pages.
4664 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4665 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4666 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4668 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4669 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4670 string_heap_insert_mstring (&assembly->sheap, tb->name);
4673 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4674 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4675 mono_image_get_type_info (domain, type, assembly);
4679 * table->rows is already set above and in mono_image_fill_module_table.
4681 /* add all the custom attributes at the end, once all the indexes are stable */
4682 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4684 /* CAS assembly permissions */
4685 if (assemblyb->permissions_minimum)
4686 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4687 if (assemblyb->permissions_optional)
4688 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4689 if (assemblyb->permissions_refused)
4690 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4692 module_add_cattrs (assembly, moduleb);
4695 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4697 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4698 * the final tokens and don't need another fixup pass. */
4700 if (moduleb->global_methods) {
4701 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4702 MonoReflectionMethodBuilder *mb = mono_array_get (
4703 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4704 mono_image_add_methodimpl (assembly, mb);
4708 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4709 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4710 if (type->methods) {
4711 for (j = 0; j < type->num_methods; ++j) {
4712 MonoReflectionMethodBuilder *mb = mono_array_get (
4713 type->methods, MonoReflectionMethodBuilder*, j);
4715 mono_image_add_methodimpl (assembly, mb);
4720 mono_ptr_array_destroy (types);
4722 fixup_cattrs (assembly);
4725 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4728 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4730 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4733 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4737 guint32 import_lookup_table;
4741 guint32 import_address_table_rva;
4749 #ifndef DISABLE_REFLECTION_EMIT
4752 * mono_image_insert_string:
4753 * @module: module builder object
4756 * Insert @str into the user string stream of @module.
4759 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4761 MonoDynamicImage *assembly;
4766 if (!module->dynamic_image)
4767 mono_image_module_basic_init (module);
4769 assembly = module->dynamic_image;
4771 if (assembly->save) {
4772 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4773 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4774 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4776 char *swapped = g_malloc (2 * mono_string_length (str));
4777 const char *p = (const char*)mono_string_chars (str);
4779 swap_with_size (swapped, p, 2, mono_string_length (str));
4780 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4784 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4786 mono_image_add_stream_data (&assembly->us, "", 1);
4788 idx = assembly->us.index ++;
4791 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4793 return MONO_TOKEN_STRING | idx;
4797 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4801 MonoMethodSignature *sig;
4803 klass = obj->vtable->klass;
4804 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4805 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4806 MonoMethodSignature *old;
4807 guint32 sig_token, parent;
4810 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4812 nargs = mono_array_length (opt_param_types);
4813 old = mono_method_signature (method);
4814 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4816 sig->hasthis = old->hasthis;
4817 sig->explicit_this = old->explicit_this;
4818 sig->call_convention = old->call_convention;
4819 sig->generic_param_count = old->generic_param_count;
4820 sig->param_count = old->param_count + nargs;
4821 sig->sentinelpos = old->param_count;
4822 sig->ret = old->ret;
4824 for (i = 0; i < old->param_count; i++)
4825 sig->params [i] = old->params [i];
4827 for (i = 0; i < nargs; i++) {
4828 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4829 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4832 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4833 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4834 parent >>= MONO_TYPEDEFORREF_BITS;
4836 parent <<= MONO_MEMBERREF_PARENT_BITS;
4837 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4839 sig_token = method_encode_signature (assembly, sig);
4840 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4841 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4842 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4843 ReflectionMethodBuilder rmb;
4844 guint32 parent, sig_token;
4845 int nopt_args, nparams, ngparams, i;
4848 reflection_methodbuilder_from_method_builder (&rmb, mb);
4849 rmb.opt_types = opt_param_types;
4850 nopt_args = mono_array_length (opt_param_types);
4852 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4853 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4854 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4856 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4857 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4858 sig->call_convention = rmb.call_conv;
4859 sig->generic_param_count = ngparams;
4860 sig->param_count = nparams + nopt_args;
4861 sig->sentinelpos = nparams;
4862 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4864 for (i = 0; i < nparams; i++) {
4865 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4866 sig->params [i] = mono_reflection_type_get_handle (rt);
4869 for (i = 0; i < nopt_args; i++) {
4870 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4871 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4874 sig_token = method_builder_encode_signature (assembly, &rmb);
4876 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4877 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4879 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4880 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4882 name = mono_string_to_utf8 (rmb.name);
4883 token = mono_image_get_varargs_method_token (
4884 assembly, parent, name, sig_token);
4887 g_error ("requested method token for %s\n", klass->name);
4890 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4891 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4896 * mono_image_create_token:
4897 * @assembly: a dynamic assembly
4899 * @register_token: Whenever to register the token in the assembly->tokens hash.
4901 * Get a token to insert in the IL code stream for the given MemberInfo.
4902 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4903 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4907 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4908 gboolean create_open_instance, gboolean register_token)
4913 klass = obj->vtable->klass;
4915 /* Check for user defined reflection objects */
4916 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4917 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4918 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4920 if (strcmp (klass->name, "MethodBuilder") == 0) {
4921 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4922 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4924 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4925 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4927 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4928 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4929 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4930 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4931 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4933 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4934 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4936 token = mono_image_get_ctorbuilder_token (assembly, mb);
4937 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4938 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4939 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4940 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4941 if (tb->generic_params) {
4942 token = mono_image_get_generic_field_token (assembly, fb);
4944 if (tb->module->dynamic_image == assembly) {
4945 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4947 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4950 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4951 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4952 if (create_open_instance && tb->generic_params) {
4954 init_type_builder_generics (obj);
4955 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4956 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4957 token = mono_metadata_token_from_dor (token);
4958 } else if (tb->module->dynamic_image == assembly) {
4959 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4962 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4963 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4965 } else if (strcmp (klass->name, "MonoType") == 0) {
4966 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4967 MonoClass *mc = mono_class_from_mono_type (type);
4968 token = mono_metadata_token_from_dor (
4969 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4970 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4971 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4972 token = mono_metadata_token_from_dor (
4973 mono_image_typedef_or_ref (assembly, type));
4974 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4975 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4976 token = mono_metadata_token_from_dor (
4977 mono_image_typedef_or_ref (assembly, type));
4978 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4979 strcmp (klass->name, "MonoMethod") == 0 ||
4980 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4981 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4982 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4983 if (m->method->is_inflated) {
4984 if (create_open_instance)
4985 token = mono_image_get_methodspec_token (assembly, m->method);
4987 token = mono_image_get_inflated_method_token (assembly, m->method);
4988 } else if ((m->method->klass->image == &assembly->image) &&
4989 !m->method->klass->generic_class) {
4990 static guint32 method_table_idx = 0xffffff;
4991 if (m->method->klass->wastypebuilder) {
4992 /* we use the same token as the one that was assigned
4993 * to the Methodbuilder.
4994 * FIXME: do the equivalent for Fields.
4996 token = m->method->token;
4999 * Each token should have a unique index, but the indexes are
5000 * assigned by managed code, so we don't know about them. An
5001 * easy solution is to count backwards...
5003 method_table_idx --;
5004 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5007 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5009 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5010 } else if (strcmp (klass->name, "MonoField") == 0) {
5011 MonoReflectionField *f = (MonoReflectionField *)obj;
5012 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5013 static guint32 field_table_idx = 0xffffff;
5015 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5017 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5019 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5020 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5021 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5022 token = mono_image_get_array_token (assembly, m);
5023 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5024 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5025 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5026 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5027 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5028 token = mono_metadata_token_from_dor (
5029 mono_image_typedef_or_ref (assembly, type));
5030 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5031 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5032 token = mono_image_get_field_on_inst_token (assembly, f);
5033 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5034 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5035 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5036 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5037 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5038 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5039 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5040 MonoReflectionType *type = (MonoReflectionType *)obj;
5041 token = mono_metadata_token_from_dor (
5042 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5044 g_error ("requested token for %s\n", klass->name);
5048 mono_image_register_token (assembly, token, obj);
5054 * mono_image_register_token:
5056 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5057 * the Module.ResolveXXXToken () methods to work.
5060 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5062 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5064 /* There could be multiple MethodInfo objects with the same token */
5065 //g_assert (prev == obj);
5067 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5071 static MonoDynamicImage*
5072 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5074 static const guchar entrycode [16] = {0xff, 0x25, 0};
5075 MonoDynamicImage *image;
5078 const char *version;
5080 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5081 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5083 version = mono_get_runtime_info ()->runtime_version;
5086 /* The MonoGHashTable's need GC tracking */
5087 image = GC_MALLOC (sizeof (MonoDynamicImage));
5089 image = g_new0 (MonoDynamicImage, 1);
5092 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5094 /*g_print ("created image %p\n", image);*/
5095 /* keep in sync with image.c */
5096 image->image.name = assembly_name;
5097 image->image.assembly_name = image->image.name; /* they may be different */
5098 image->image.module_name = module_name;
5099 image->image.version = g_strdup (version);
5100 image->image.md_version_major = 1;
5101 image->image.md_version_minor = 1;
5102 image->image.dynamic = TRUE;
5104 image->image.references = g_new0 (MonoAssembly*, 1);
5105 image->image.references [0] = NULL;
5107 mono_image_init (&image->image);
5109 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5110 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5111 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5112 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5113 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5114 image->handleref = g_hash_table_new (NULL, NULL);
5115 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5116 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5117 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5118 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5119 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5120 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5121 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5122 image->gen_params = g_ptr_array_new ();
5123 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5125 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5126 string_heap_init (&image->sheap);
5127 mono_image_add_stream_data (&image->us, "", 1);
5128 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5129 /* import tables... */
5130 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5131 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5132 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5133 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5134 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5135 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5136 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5137 stream_data_align (&image->code);
5139 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5141 for (i=0; i < MONO_TABLE_NUM; ++i) {
5142 image->tables [i].next_idx = 1;
5143 image->tables [i].columns = table_sizes [i];
5146 image->image.assembly = (MonoAssembly*)assembly;
5147 image->run = assembly->run;
5148 image->save = assembly->save;
5149 image->pe_kind = 0x1; /* ILOnly */
5150 image->machine = 0x14c; /* I386 */
5152 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5159 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5165 release_hashtable (MonoGHashTable **hash)
5168 mono_g_hash_table_destroy (*hash);
5174 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5176 release_hashtable (&image->token_fixups);
5177 release_hashtable (&image->handleref_managed);
5178 release_hashtable (&image->tokens);
5179 release_hashtable (&image->remapped_tokens);
5180 release_hashtable (&image->generic_def_objects);
5181 release_hashtable (&image->methodspec);
5185 mono_dynamic_image_free (MonoDynamicImage *image)
5187 MonoDynamicImage *di = image;
5192 mono_g_hash_table_destroy (di->methodspec);
5194 g_hash_table_destroy (di->typespec);
5196 g_hash_table_destroy (di->typeref);
5198 g_hash_table_destroy (di->handleref);
5199 if (di->handleref_managed)
5200 mono_g_hash_table_destroy (di->handleref_managed);
5202 mono_g_hash_table_destroy (di->tokens);
5203 if (di->remapped_tokens)
5204 mono_g_hash_table_destroy (di->remapped_tokens);
5205 if (di->generic_def_objects)
5206 mono_g_hash_table_destroy (di->generic_def_objects);
5207 if (di->blob_cache) {
5208 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5209 g_hash_table_destroy (di->blob_cache);
5211 if (di->standalonesig_cache)
5212 g_hash_table_destroy (di->standalonesig_cache);
5213 for (list = di->array_methods; list; list = list->next) {
5214 ArrayMethod *am = (ArrayMethod *)list->data;
5219 g_list_free (di->array_methods);
5220 if (di->gen_params) {
5221 for (i = 0; i < di->gen_params->len; i++) {
5222 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5223 mono_gc_deregister_root ((char*) &entry->gparam);
5226 g_ptr_array_free (di->gen_params, TRUE);
5228 if (di->token_fixups)
5229 mono_g_hash_table_destroy (di->token_fixups);
5230 if (di->method_to_table_idx)
5231 g_hash_table_destroy (di->method_to_table_idx);
5232 if (di->field_to_table_idx)
5233 g_hash_table_destroy (di->field_to_table_idx);
5234 if (di->method_aux_hash)
5235 g_hash_table_destroy (di->method_aux_hash);
5236 if (di->vararg_aux_hash)
5237 g_hash_table_destroy (di->vararg_aux_hash);
5238 g_free (di->strong_name);
5239 g_free (di->win32_res);
5241 g_free (di->public_key);
5243 /*g_print ("string heap destroy for image %p\n", di);*/
5244 mono_dynamic_stream_reset (&di->sheap);
5245 mono_dynamic_stream_reset (&di->code);
5246 mono_dynamic_stream_reset (&di->resources);
5247 mono_dynamic_stream_reset (&di->us);
5248 mono_dynamic_stream_reset (&di->blob);
5249 mono_dynamic_stream_reset (&di->tstream);
5250 mono_dynamic_stream_reset (&di->guid);
5251 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5252 g_free (di->tables [i].values);
5257 mono_dynamic_image_free_image (MonoDynamicImage *image)
5259 /* See create_dynamic_mono_image () */
5261 /* Allocated using GC_MALLOC */
5267 #ifndef DISABLE_REFLECTION_EMIT
5270 * mono_image_basic_init:
5271 * @assembly: an assembly builder object
5273 * Create the MonoImage that represents the assembly builder and setup some
5274 * of the helper hash table and the basic metadata streams.
5277 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5279 MonoDynamicAssembly *assembly;
5280 MonoDynamicImage *image;
5281 MonoDomain *domain = mono_object_domain (assemblyb);
5283 if (assemblyb->dynamic_assembly)
5287 /* assembly->assembly.image might be GC allocated */
5288 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5290 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5293 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5295 assembly->assembly.ref_count = 1;
5296 assembly->assembly.dynamic = TRUE;
5297 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5298 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5299 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5300 if (assemblyb->culture)
5301 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5303 assembly->assembly.aname.culture = g_strdup ("");
5305 if (assemblyb->version) {
5306 char *vstr = mono_string_to_utf8 (assemblyb->version);
5307 char **version = g_strsplit (vstr, ".", 4);
5308 char **parts = version;
5309 assembly->assembly.aname.major = atoi (*parts++);
5310 assembly->assembly.aname.minor = atoi (*parts++);
5311 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5312 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5314 g_strfreev (version);
5317 assembly->assembly.aname.major = 0;
5318 assembly->assembly.aname.minor = 0;
5319 assembly->assembly.aname.build = 0;
5320 assembly->assembly.aname.revision = 0;
5323 assembly->run = assemblyb->access != 2;
5324 assembly->save = assemblyb->access != 1;
5325 assembly->domain = domain;
5327 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5328 image->initial_image = TRUE;
5329 assembly->assembly.aname.name = image->image.name;
5330 assembly->assembly.image = &image->image;
5331 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5332 /* -1 to correct for the trailing NULL byte */
5333 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5334 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5336 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5339 mono_domain_assemblies_lock (domain);
5340 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5341 mono_domain_assemblies_unlock (domain);
5343 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5345 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5347 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5350 #endif /* !DISABLE_REFLECTION_EMIT */
5352 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5355 calc_section_size (MonoDynamicImage *assembly)
5359 /* alignment constraints */
5360 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5361 g_assert ((assembly->code.index % 4) == 0);
5362 assembly->meta_size += 3;
5363 assembly->meta_size &= ~3;
5364 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5365 g_assert ((assembly->resources.index % 4) == 0);
5367 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5368 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5371 if (assembly->win32_res) {
5372 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5374 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5375 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5379 assembly->sections [MONO_SECTION_RELOC].size = 12;
5380 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5390 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5394 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5396 ResTreeNode *t1 = (ResTreeNode*)a;
5397 ResTreeNode *t2 = (ResTreeNode*)b;
5399 return t1->id - t2->id;
5403 * resource_tree_create:
5405 * Organize the resources into a resource tree.
5407 static ResTreeNode *
5408 resource_tree_create (MonoArray *win32_resources)
5410 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5414 tree = g_new0 (ResTreeNode, 1);
5416 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5417 MonoReflectionWin32Resource *win32_res =
5418 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5422 /* FIXME: BUG: this stores managed references in unmanaged memory */
5423 lang_node = g_new0 (ResTreeNode, 1);
5424 lang_node->id = win32_res->lang_id;
5425 lang_node->win32_res = win32_res;
5427 /* Create type node if neccesary */
5429 for (l = tree->children; l; l = l->next)
5430 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5431 type_node = (ResTreeNode*)l->data;
5436 type_node = g_new0 (ResTreeNode, 1);
5437 type_node->id = win32_res->res_type;
5440 * The resource types have to be sorted otherwise
5441 * Windows Explorer can't display the version information.
5443 tree->children = g_slist_insert_sorted (tree->children,
5444 type_node, resource_tree_compare_by_id);
5447 /* Create res node if neccesary */
5449 for (l = type_node->children; l; l = l->next)
5450 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5451 res_node = (ResTreeNode*)l->data;
5456 res_node = g_new0 (ResTreeNode, 1);
5457 res_node->id = win32_res->res_id;
5458 type_node->children = g_slist_append (type_node->children, res_node);
5461 res_node->children = g_slist_append (res_node->children, lang_node);
5468 * resource_tree_encode:
5470 * Encode the resource tree into the format used in the PE file.
5473 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5476 MonoPEResourceDir dir;
5477 MonoPEResourceDirEntry dir_entry;
5478 MonoPEResourceDataEntry data_entry;
5480 guint32 res_id_entries;
5483 * For the format of the resource directory, see the article
5484 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5488 memset (&dir, 0, sizeof (dir));
5489 memset (&dir_entry, 0, sizeof (dir_entry));
5490 memset (&data_entry, 0, sizeof (data_entry));
5492 g_assert (sizeof (dir) == 16);
5493 g_assert (sizeof (dir_entry) == 8);
5494 g_assert (sizeof (data_entry) == 16);
5496 node->offset = p - begin;
5498 /* IMAGE_RESOURCE_DIRECTORY */
5499 res_id_entries = g_slist_length (node->children);
5500 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5502 memcpy (p, &dir, sizeof (dir));
5505 /* Reserve space for entries */
5507 p += sizeof (dir_entry) * res_id_entries;
5509 /* Write children */
5510 for (l = node->children; l; l = l->next) {
5511 ResTreeNode *child = (ResTreeNode*)l->data;
5513 if (child->win32_res) {
5516 child->offset = p - begin;
5518 /* IMAGE_RESOURCE_DATA_ENTRY */
5519 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5520 size = mono_array_length (child->win32_res->res_data);
5521 data_entry.rde_size = GUINT32_TO_LE (size);
5523 memcpy (p, &data_entry, sizeof (data_entry));
5524 p += sizeof (data_entry);
5526 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5529 resource_tree_encode (child, begin, p, &p);
5533 /* IMAGE_RESOURCE_ENTRY */
5534 for (l = node->children; l; l = l->next) {
5535 ResTreeNode *child = (ResTreeNode*)l->data;
5537 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5538 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5540 memcpy (entries, &dir_entry, sizeof (dir_entry));
5541 entries += sizeof (dir_entry);
5548 resource_tree_free (ResTreeNode * node)
5551 for (list = node->children; list; list = list->next)
5552 resource_tree_free ((ResTreeNode*)list->data);
5553 g_slist_free(node->children);
5558 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5563 MonoReflectionWin32Resource *win32_res;
5566 if (!assemblyb->win32_resources)
5570 * Resources are stored in a three level tree inside the PE file.
5571 * - level one contains a node for each type of resource
5572 * - level two contains a node for each resource
5573 * - level three contains a node for each instance of a resource for a
5574 * specific language.
5577 tree = resource_tree_create (assemblyb->win32_resources);
5579 /* Estimate the size of the encoded tree */
5581 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5582 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5583 size += mono_array_length (win32_res->res_data);
5585 /* Directory structure */
5586 size += mono_array_length (assemblyb->win32_resources) * 256;
5587 p = buf = g_malloc (size);
5589 resource_tree_encode (tree, p, p, &p);
5591 g_assert (p - buf <= size);
5593 assembly->win32_res = g_malloc (p - buf);
5594 assembly->win32_res_size = p - buf;
5595 memcpy (assembly->win32_res, buf, p - buf);
5598 resource_tree_free (tree);
5602 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5604 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5607 p += sizeof (MonoPEResourceDir);
5608 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5609 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5610 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5611 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5612 fixup_resource_directory (res_section, child, rva);
5614 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5615 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5618 p += sizeof (MonoPEResourceDirEntry);
5623 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5626 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5627 g_error ("WriteFile returned %d\n", GetLastError ());
5631 * mono_image_create_pefile:
5632 * @mb: a module builder object
5634 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5635 * assembly->pefile where it can be easily retrieved later in chunks.
5638 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5640 MonoMSDOSHeader *msdos;
5641 MonoDotNetHeader *header;
5642 MonoSectionTable *section;
5643 MonoCLIHeader *cli_header;
5644 guint32 size, image_size, virtual_base, text_offset;
5645 guint32 header_start, section_start, file_offset, virtual_offset;
5646 MonoDynamicImage *assembly;
5647 MonoReflectionAssemblyBuilder *assemblyb;
5648 MonoDynamicStream pefile_stream = {0};
5649 MonoDynamicStream *pefile = &pefile_stream;
5651 guint32 *rva, value;
5653 static const unsigned char msheader[] = {
5654 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5655 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5658 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5659 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5660 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5661 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5664 assemblyb = mb->assemblyb;
5666 mono_image_basic_init (assemblyb);
5667 assembly = mb->dynamic_image;
5669 assembly->pe_kind = assemblyb->pe_kind;
5670 assembly->machine = assemblyb->machine;
5671 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5672 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5674 mono_image_build_metadata (mb);
5676 if (mb->is_main && assemblyb->resources) {
5677 int len = mono_array_length (assemblyb->resources);
5678 for (i = 0; i < len; ++i)
5679 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5682 if (mb->resources) {
5683 int len = mono_array_length (mb->resources);
5684 for (i = 0; i < len; ++i)
5685 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5688 build_compressed_metadata (assembly);
5691 assembly_add_win32_resources (assembly, assemblyb);
5693 nsections = calc_section_size (assembly);
5695 /* The DOS header and stub */
5696 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5697 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5699 /* the dotnet header */
5700 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5702 /* the section tables */
5703 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5705 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5706 virtual_offset = VIRT_ALIGN;
5709 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5710 if (!assembly->sections [i].size)
5713 file_offset += FILE_ALIGN - 1;
5714 file_offset &= ~(FILE_ALIGN - 1);
5715 virtual_offset += VIRT_ALIGN - 1;
5716 virtual_offset &= ~(VIRT_ALIGN - 1);
5718 assembly->sections [i].offset = file_offset;
5719 assembly->sections [i].rva = virtual_offset;
5721 file_offset += assembly->sections [i].size;
5722 virtual_offset += assembly->sections [i].size;
5723 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5726 file_offset += FILE_ALIGN - 1;
5727 file_offset &= ~(FILE_ALIGN - 1);
5729 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5731 /* back-patch info */
5732 msdos = (MonoMSDOSHeader*)pefile->data;
5733 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5735 header = (MonoDotNetHeader*)(pefile->data + header_start);
5736 header->pesig [0] = 'P';
5737 header->pesig [1] = 'E';
5739 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5740 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5741 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5742 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5743 if (assemblyb->pekind == 1) {
5745 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5748 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5751 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5753 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5754 header->pe.pe_major = 6;
5755 header->pe.pe_minor = 0;
5756 size = assembly->sections [MONO_SECTION_TEXT].size;
5757 size += FILE_ALIGN - 1;
5758 size &= ~(FILE_ALIGN - 1);
5759 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5760 size = assembly->sections [MONO_SECTION_RSRC].size;
5761 size += FILE_ALIGN - 1;
5762 size &= ~(FILE_ALIGN - 1);
5763 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5764 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5765 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5766 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5767 /* pe_rva_entry_point always at the beginning of the text section */
5768 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5770 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5771 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5772 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5773 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5774 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5775 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5776 size = section_start;
5777 size += FILE_ALIGN - 1;
5778 size &= ~(FILE_ALIGN - 1);
5779 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5781 size += VIRT_ALIGN - 1;
5782 size &= ~(VIRT_ALIGN - 1);
5783 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5786 // Translate the PEFileKind value to the value expected by the Windows loader
5792 // PEFileKinds.Dll == 1
5793 // PEFileKinds.ConsoleApplication == 2
5794 // PEFileKinds.WindowApplication == 3
5797 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5798 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5800 if (assemblyb->pekind == 3)
5805 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5807 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5808 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5809 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5810 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5811 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5812 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5814 /* fill data directory entries */
5816 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5817 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5819 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5820 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5822 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5823 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5824 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5825 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5826 /* patch entrypoint name */
5827 if (assemblyb->pekind == 1)
5828 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5830 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5831 /* patch imported function RVA name */
5832 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5833 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5835 /* the import table */
5836 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5837 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5838 /* patch imported dll RVA name and other entries in the dir */
5839 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5840 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5841 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5842 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5843 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5844 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5846 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5847 value = (assembly->text_rva + assembly->imp_names_offset);
5848 *p++ = (value) & 0xff;
5849 *p++ = (value >> 8) & (0xff);
5850 *p++ = (value >> 16) & (0xff);
5851 *p++ = (value >> 24) & (0xff);
5853 /* the CLI header info */
5854 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5855 cli_header->ch_size = GUINT32_FROM_LE (72);
5856 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5857 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5858 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5859 if (assemblyb->entry_point) {
5860 guint32 table_idx = 0;
5861 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5862 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5863 table_idx = methodb->table_idx;
5865 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5867 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5869 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5871 /* The embedded managed resources */
5872 text_offset = assembly->text_rva + assembly->code.index;
5873 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5874 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5875 text_offset += assembly->resources.index;
5876 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5877 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5878 text_offset += assembly->meta_size;
5879 if (assembly->strong_name_size) {
5880 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5881 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5882 text_offset += assembly->strong_name_size;
5885 /* write the section tables and section content */
5886 section = (MonoSectionTable*)(pefile->data + section_start);
5887 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5888 static const char section_names [][7] = {
5889 ".text", ".rsrc", ".reloc"
5891 if (!assembly->sections [i].size)
5893 strcpy (section->st_name, section_names [i]);
5894 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5895 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5896 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5897 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5898 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5899 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5900 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5904 checked_write_file (file, pefile->data, pefile->index);
5906 mono_dynamic_stream_reset (pefile);
5908 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5909 if (!assembly->sections [i].size)
5912 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5913 g_error ("SetFilePointer returned %d\n", GetLastError ());
5916 case MONO_SECTION_TEXT:
5917 /* patch entry point */
5918 p = (guchar*)(assembly->code.data + 2);
5919 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5920 *p++ = (value) & 0xff;
5921 *p++ = (value >> 8) & 0xff;
5922 *p++ = (value >> 16) & 0xff;
5923 *p++ = (value >> 24) & 0xff;
5925 checked_write_file (file, assembly->code.data, assembly->code.index);
5926 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5927 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5928 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5931 g_free (assembly->image.raw_metadata);
5933 case MONO_SECTION_RELOC: {
5937 guint16 type_and_offset;
5941 g_assert (sizeof (reloc) == 12);
5943 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5944 reloc.block_size = GUINT32_FROM_LE (12);
5947 * the entrypoint is always at the start of the text section
5948 * 3 is IMAGE_REL_BASED_HIGHLOW
5949 * 2 is patch_size_rva - text_rva
5951 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5954 checked_write_file (file, &reloc, sizeof (reloc));
5958 case MONO_SECTION_RSRC:
5959 if (assembly->win32_res) {
5961 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5962 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5963 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5967 g_assert_not_reached ();
5971 /* check that the file is properly padded */
5972 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5973 g_error ("SetFilePointer returned %d\n", GetLastError ());
5974 if (! SetEndOfFile (file))
5975 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5977 mono_dynamic_stream_reset (&assembly->code);
5978 mono_dynamic_stream_reset (&assembly->us);
5979 mono_dynamic_stream_reset (&assembly->blob);
5980 mono_dynamic_stream_reset (&assembly->guid);
5981 mono_dynamic_stream_reset (&assembly->sheap);
5983 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5984 g_hash_table_destroy (assembly->blob_cache);
5985 assembly->blob_cache = NULL;
5988 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5991 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5993 g_assert_not_reached ();
5996 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5998 #ifndef DISABLE_REFLECTION_EMIT
6000 MonoReflectionModule *
6001 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6005 MonoImageOpenStatus status;
6006 MonoDynamicAssembly *assembly;
6007 guint32 module_count;
6008 MonoImage **new_modules;
6009 gboolean *new_modules_loaded;
6011 name = mono_string_to_utf8 (fileName);
6013 image = mono_image_open (name, &status);
6016 if (status == MONO_IMAGE_ERROR_ERRNO)
6017 exc = mono_get_exception_file_not_found (fileName);
6019 exc = mono_get_exception_bad_image_format (name);
6021 mono_raise_exception (exc);
6026 assembly = ab->dynamic_assembly;
6027 image->assembly = (MonoAssembly*)assembly;
6029 module_count = image->assembly->image->module_count;
6030 new_modules = g_new0 (MonoImage *, module_count + 1);
6031 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6033 if (image->assembly->image->modules)
6034 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6035 if (image->assembly->image->modules_loaded)
6036 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6037 new_modules [module_count] = image;
6038 new_modules_loaded [module_count] = TRUE;
6039 mono_image_addref (image);
6041 g_free (image->assembly->image->modules);
6042 image->assembly->image->modules = new_modules;
6043 image->assembly->image->modules_loaded = new_modules_loaded;
6044 image->assembly->image->module_count ++;
6046 mono_assembly_load_references (image, &status);
6048 mono_image_close (image);
6049 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6052 return mono_module_get_object (mono_domain_get (), image);
6055 #endif /* DISABLE_REFLECTION_EMIT */
6058 * We need to return always the same object for MethodInfo, FieldInfo etc..
6059 * but we need to consider the reflected type.
6060 * type uses a different hash, since it uses custom hash/equal functions.
6065 MonoClass *refclass;
6069 reflected_equal (gconstpointer a, gconstpointer b) {
6070 const ReflectedEntry *ea = a;
6071 const ReflectedEntry *eb = b;
6073 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6077 reflected_hash (gconstpointer a) {
6078 const ReflectedEntry *ea = a;
6079 return mono_aligned_addr_hash (ea->item);
6082 #define CHECK_OBJECT(t,p,k) \
6088 mono_domain_lock (domain); \
6089 if (!domain->refobject_hash) \
6090 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6091 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6092 mono_domain_unlock (domain); \
6095 mono_domain_unlock (domain); \
6098 #ifdef HAVE_BOEHM_GC
6099 /* ReflectedEntry doesn't need to be GC tracked */
6100 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6101 #define FREE_REFENTRY(entry) g_free ((entry))
6102 #define REFENTRY_REQUIRES_CLEANUP
6104 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6106 #define FREE_REFENTRY(entry)
6109 #define CACHE_OBJECT(t,p,o,k) \
6112 ReflectedEntry pe; \
6114 pe.refclass = (k); \
6115 mono_domain_lock (domain); \
6116 if (!domain->refobject_hash) \
6117 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6118 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6120 ReflectedEntry *e = ALLOC_REFENTRY; \
6122 e->refclass = (k); \
6123 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6126 mono_domain_unlock (domain); \
6131 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6133 mono_domain_lock (domain);
6134 if (domain->refobject_hash) {
6136 gpointer orig_pe, orig_value;
6139 pe.refclass = klass;
6140 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6141 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6142 FREE_REFENTRY (orig_pe);
6145 mono_domain_unlock (domain);
6148 #ifdef REFENTRY_REQUIRES_CLEANUP
6150 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6152 FREE_REFENTRY (key);
6157 mono_reflection_cleanup_domain (MonoDomain *domain)
6159 if (domain->refobject_hash) {
6160 /*let's avoid scanning the whole hashtable if not needed*/
6161 #ifdef REFENTRY_REQUIRES_CLEANUP
6162 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6164 mono_g_hash_table_destroy (domain->refobject_hash);
6165 domain->refobject_hash = NULL;
6169 #ifndef DISABLE_REFLECTION_EMIT
6171 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6173 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6177 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6179 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6183 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6185 MonoDynamicImage *image = moduleb->dynamic_image;
6186 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6190 MonoImage **new_modules;
6192 char *name, *fqname;
6194 * FIXME: we already created an image in mono_image_basic_init (), but
6195 * we don't know which module it belongs to, since that is only
6196 * determined at assembly save time.
6198 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6199 name = mono_string_to_utf8 (ab->name);
6200 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6201 if (!mono_error_ok (&error)) {
6203 mono_error_raise_exception (&error);
6205 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6207 moduleb->module.image = &image->image;
6208 moduleb->dynamic_image = image;
6209 register_module (mono_object_domain (moduleb), moduleb, image);
6211 /* register the module with the assembly */
6212 ass = ab->dynamic_assembly->assembly.image;
6213 module_count = ass->module_count;
6214 new_modules = g_new0 (MonoImage *, module_count + 1);
6217 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6218 new_modules [module_count] = &image->image;
6219 mono_image_addref (&image->image);
6221 g_free (ass->modules);
6222 ass->modules = new_modules;
6223 ass->module_count ++;
6228 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6230 MonoDynamicImage *image = moduleb->dynamic_image;
6232 g_assert (type->type);
6233 image->wrappers_type = mono_class_from_mono_type (type->type);
6239 * mono_assembly_get_object:
6240 * @domain: an app domain
6241 * @assembly: an assembly
6243 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6245 MonoReflectionAssembly*
6246 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6248 static MonoClass *assembly_type;
6249 MonoReflectionAssembly *res;
6251 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6252 if (!assembly_type) {
6253 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6255 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6257 assembly_type = class;
6259 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6260 res->assembly = assembly;
6262 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6267 MonoReflectionModule*
6268 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6270 static MonoClass *module_type;
6271 MonoReflectionModule *res;
6274 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6276 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6278 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6280 module_type = class;
6282 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6285 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6287 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6288 basename = g_path_get_basename (image->name);
6289 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6290 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6294 if (image->assembly->image == image) {
6295 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6299 if (image->assembly->image->modules) {
6300 for (i = 0; i < image->assembly->image->module_count; i++) {
6301 if (image->assembly->image->modules [i] == image)
6302 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6304 g_assert (res->token);
6308 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6311 MonoReflectionModule*
6312 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6314 static MonoClass *module_type;
6315 MonoReflectionModule *res;
6316 MonoTableInfo *table;
6317 guint32 cols [MONO_FILE_SIZE];
6319 guint32 i, name_idx;
6323 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6325 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6327 module_type = class;
6329 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6331 table = &image->tables [MONO_TABLE_FILE];
6332 g_assert (table_index < table->rows);
6333 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6336 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6337 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6339 /* Check whenever the row has a corresponding row in the moduleref table */
6340 table = &image->tables [MONO_TABLE_MODULEREF];
6341 for (i = 0; i < table->rows; ++i) {
6342 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6343 val = mono_metadata_string_heap (image, name_idx);
6344 if (strcmp (val, name) == 0)
6345 res->image = image->modules [i];
6348 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6349 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6350 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6351 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6352 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6358 verify_safe_for_managed_space (MonoType *type)
6360 switch (type->type) {
6362 case MONO_TYPE_ARRAY:
6363 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6365 return verify_safe_for_managed_space (type->data.type);
6366 case MONO_TYPE_SZARRAY:
6367 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6368 case MONO_TYPE_GENERICINST: {
6369 MonoGenericInst *inst = type->data.generic_class->inst;
6373 for (i = 0; i < inst->type_argc; ++i)
6374 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6380 case MONO_TYPE_MVAR:
6388 mono_type_normalize (MonoType *type)
6391 MonoGenericClass *gclass;
6392 MonoGenericInst *ginst;
6394 MonoGenericContainer *gcontainer;
6395 MonoType **argv = NULL;
6396 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6398 if (type->type != MONO_TYPE_GENERICINST)
6401 gclass = type->data.generic_class;
6402 ginst = gclass->context.class_inst;
6403 if (!ginst->is_open)
6406 gtd = gclass->container_class;
6407 gcontainer = gtd->generic_container;
6408 argv = g_newa (MonoType*, ginst->type_argc);
6410 for (i = 0; i < ginst->type_argc; ++i) {
6411 MonoType *t = ginst->type_argv [i], *norm;
6412 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6413 is_denorm_gtd = FALSE;
6414 norm = mono_type_normalize (t);
6417 requires_rebind = TRUE;
6421 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6423 if (requires_rebind) {
6424 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6425 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6431 * mono_type_get_object:
6432 * @domain: an app domain
6435 * Return an System.MonoType object representing the type @type.
6438 mono_type_get_object (MonoDomain *domain, MonoType *type)
6440 MonoType *norm_type;
6441 MonoReflectionType *res;
6442 MonoClass *klass = mono_class_from_mono_type (type);
6444 /*we must avoid using @type as it might have come
6445 * from a mono_metadata_type_dup and the caller
6446 * expects that is can be freed.
6447 * Using the right type from
6449 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6451 /* void is very common */
6452 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6453 return (MonoReflectionType*)domain->typeof_void;
6456 * If the vtable of the given class was already created, we can use
6457 * the MonoType from there and avoid all locking and hash table lookups.
6459 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6460 * that the resulting object is different.
6462 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6463 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6464 if (vtable && vtable->type)
6465 return vtable->type;
6468 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6469 mono_domain_lock (domain);
6470 if (!domain->type_hash)
6471 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6472 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6473 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6474 mono_domain_unlock (domain);
6475 mono_loader_unlock ();
6479 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6480 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6481 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6482 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6483 * artifact of how generics are encoded and should be transparent to managed code so we
6484 * need to weed out this diference when retrieving managed System.Type objects.
6486 norm_type = mono_type_normalize (type);
6487 if (norm_type != type) {
6488 res = mono_type_get_object (domain, norm_type);
6489 mono_g_hash_table_insert (domain->type_hash, type, res);
6490 mono_domain_unlock (domain);
6491 mono_loader_unlock ();
6495 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6496 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6499 if (!verify_safe_for_managed_space (type)) {
6500 mono_domain_unlock (domain);
6501 mono_loader_unlock ();
6502 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6505 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6506 gboolean is_type_done = TRUE;
6507 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6508 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6509 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6511 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6512 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6514 if (gparam->owner && gparam->owner->is_method) {
6515 MonoMethod *method = gparam->owner->owner.method;
6516 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6517 is_type_done = FALSE;
6518 } else if (gparam->owner && !gparam->owner->is_method) {
6519 MonoClass *klass = gparam->owner->owner.klass;
6520 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6521 is_type_done = FALSE;
6525 /* g_assert_not_reached (); */
6526 /* should this be considered an error condition? */
6527 if (is_type_done && !type->byref) {
6528 mono_domain_unlock (domain);
6529 mono_loader_unlock ();
6530 return mono_class_get_ref_info (klass);
6533 /* This is stored in vtables/JITted code so it has to be pinned */
6534 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6536 mono_g_hash_table_insert (domain->type_hash, type, res);
6538 if (type->type == MONO_TYPE_VOID)
6539 domain->typeof_void = (MonoObject*)res;
6541 mono_domain_unlock (domain);
6542 mono_loader_unlock ();
6547 * mono_method_get_object:
6548 * @domain: an app domain
6550 * @refclass: the reflected type (can be NULL)
6552 * Return an System.Reflection.MonoMethod object representing the method @method.
6554 MonoReflectionMethod*
6555 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6558 * We use the same C representation for methods and constructors, but the type
6559 * name in C# is different.
6561 static MonoClass *System_Reflection_MonoMethod = NULL;
6562 static MonoClass *System_Reflection_MonoCMethod = NULL;
6563 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6564 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6566 MonoReflectionMethod *ret;
6568 if (method->is_inflated) {
6569 MonoReflectionGenericMethod *gret;
6571 refclass = method->klass;
6572 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6573 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6574 if (!System_Reflection_MonoGenericCMethod)
6575 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6576 klass = System_Reflection_MonoGenericCMethod;
6578 if (!System_Reflection_MonoGenericMethod)
6579 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6580 klass = System_Reflection_MonoGenericMethod;
6582 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6583 gret->method.method = method;
6584 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6585 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6586 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6590 refclass = method->klass;
6592 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6593 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6594 if (!System_Reflection_MonoCMethod)
6595 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6596 klass = System_Reflection_MonoCMethod;
6599 if (!System_Reflection_MonoMethod)
6600 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6601 klass = System_Reflection_MonoMethod;
6603 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6604 ret->method = method;
6605 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6606 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6610 * mono_method_clear_object:
6612 * Clear the cached reflection objects for the dynamic method METHOD.
6615 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6618 g_assert (method_is_dynamic (method));
6620 klass = method->klass;
6622 clear_cached_object (domain, method, klass);
6623 klass = klass->parent;
6625 /* Added by mono_param_get_objects () */
6626 clear_cached_object (domain, &(method->signature), NULL);
6627 klass = method->klass;
6629 clear_cached_object (domain, &(method->signature), klass);
6630 klass = klass->parent;
6635 * mono_field_get_object:
6636 * @domain: an app domain
6640 * Return an System.Reflection.MonoField object representing the field @field
6643 MonoReflectionField*
6644 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6646 MonoReflectionField *res;
6647 static MonoClass *monofield_klass;
6649 CHECK_OBJECT (MonoReflectionField *, field, klass);
6650 if (!monofield_klass)
6651 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6652 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6655 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6657 if (is_field_on_inst (field)) {
6658 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6659 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6662 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6663 res->attrs = mono_field_get_flags (field);
6665 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6669 * mono_property_get_object:
6670 * @domain: an app domain
6672 * @property: a property
6674 * Return an System.Reflection.MonoProperty object representing the property @property
6677 MonoReflectionProperty*
6678 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6680 MonoReflectionProperty *res;
6681 static MonoClass *monoproperty_klass;
6683 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6684 if (!monoproperty_klass)
6685 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6686 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6688 res->property = property;
6689 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6693 * mono_event_get_object:
6694 * @domain: an app domain
6698 * Return an System.Reflection.MonoEvent object representing the event @event
6701 MonoReflectionEvent*
6702 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6704 MonoReflectionEvent *res;
6705 MonoReflectionMonoEvent *mono_event;
6706 static MonoClass *monoevent_klass;
6708 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6709 if (!monoevent_klass)
6710 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6711 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6712 mono_event->klass = klass;
6713 mono_event->event = event;
6714 res = (MonoReflectionEvent*)mono_event;
6715 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6719 * mono_get_reflection_missing_object:
6720 * @domain: Domain where the object lives
6722 * Returns the System.Reflection.Missing.Value singleton object
6723 * (of type System.Reflection.Missing).
6725 * Used as the value for ParameterInfo.DefaultValue when Optional
6729 mono_get_reflection_missing_object (MonoDomain *domain)
6732 static MonoClassField *missing_value_field = NULL;
6734 if (!missing_value_field) {
6735 MonoClass *missing_klass;
6736 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6737 mono_class_init (missing_klass);
6738 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6739 g_assert (missing_value_field);
6741 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6747 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6750 *dbnull = mono_get_dbnull_object (domain);
6755 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6757 if (!*reflection_missing)
6758 *reflection_missing = mono_get_reflection_missing_object (domain);
6759 return *reflection_missing;
6763 * mono_param_get_objects:
6764 * @domain: an app domain
6767 * Return an System.Reflection.ParameterInfo array object representing the parameters
6768 * in the method @method.
6771 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6773 static MonoClass *System_Reflection_ParameterInfo;
6774 static MonoClass *System_Reflection_ParameterInfo_array;
6776 MonoArray *res = NULL;
6777 MonoReflectionMethod *member = NULL;
6778 MonoReflectionParameter *param = NULL;
6779 char **names, **blobs = NULL;
6780 guint32 *types = NULL;
6781 MonoType *type = NULL;
6782 MonoObject *dbnull = NULL;
6783 MonoObject *missing = NULL;
6784 MonoMarshalSpec **mspecs;
6785 MonoMethodSignature *sig;
6786 MonoVTable *pinfo_vtable;
6789 if (!System_Reflection_ParameterInfo_array) {
6792 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6794 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6796 mono_memory_barrier ();
6797 System_Reflection_ParameterInfo = klass;
6800 klass = mono_array_class_get (klass, 1);
6801 mono_memory_barrier ();
6802 System_Reflection_ParameterInfo_array = klass;
6805 sig = mono_method_signature_checked (method, &error);
6806 if (!mono_error_ok (&error))
6807 mono_error_raise_exception (&error);
6809 if (!sig->param_count)
6810 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6812 /* Note: the cache is based on the address of the signature into the method
6813 * since we already cache MethodInfos with the method as keys.
6815 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6817 member = mono_method_get_object (domain, method, refclass);
6818 names = g_new (char *, sig->param_count);
6819 mono_method_get_param_names (method, (const char **) names);
6821 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6822 mono_method_get_marshal_info (method, mspecs);
6824 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6825 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6826 for (i = 0; i < sig->param_count; ++i) {
6827 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6828 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6829 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6830 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6831 param->PositionImpl = i;
6832 param->AttrsImpl = sig->params [i]->attrs;
6834 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6835 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6836 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6838 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6842 blobs = g_new0 (char *, sig->param_count);
6843 types = g_new0 (guint32, sig->param_count);
6844 get_default_param_value_blobs (method, blobs, types);
6847 /* Build MonoType for the type from the Constant Table */
6849 type = g_new0 (MonoType, 1);
6850 type->type = types [i];
6851 type->data.klass = NULL;
6852 if (types [i] == MONO_TYPE_CLASS)
6853 type->data.klass = mono_defaults.object_class;
6854 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6855 /* For enums, types [i] contains the base type */
6857 type->type = MONO_TYPE_VALUETYPE;
6858 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6860 type->data.klass = mono_class_from_mono_type (type);
6862 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6864 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6865 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6866 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6867 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6869 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6875 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6877 mono_array_setref (res, i, param);
6884 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6886 mono_metadata_free_marshal_spec (mspecs [i]);
6889 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6893 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6895 return mono_param_get_objects_internal (domain, method, NULL);
6899 * mono_method_body_get_object:
6900 * @domain: an app domain
6903 * Return an System.Reflection.MethodBody object representing the method @method.
6905 MonoReflectionMethodBody*
6906 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6908 static MonoClass *System_Reflection_MethodBody = NULL;
6909 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6910 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6911 MonoReflectionMethodBody *ret;
6912 MonoMethodHeader *header;
6914 guint32 method_rva, local_var_sig_token;
6916 unsigned char format, flags;
6919 /* for compatibility with .net */
6920 if (method_is_dynamic (method))
6921 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6923 if (!System_Reflection_MethodBody)
6924 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6925 if (!System_Reflection_LocalVariableInfo)
6926 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6927 if (!System_Reflection_ExceptionHandlingClause)
6928 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6930 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6932 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6933 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6934 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6935 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6938 image = method->klass->image;
6939 header = mono_method_get_header (method);
6941 if (!image_is_dynamic (image)) {
6942 /* Obtain local vars signature token */
6943 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6944 ptr = mono_image_rva_map (image, method_rva);
6945 flags = *(const unsigned char *) ptr;
6946 format = flags & METHOD_HEADER_FORMAT_MASK;
6948 case METHOD_HEADER_TINY_FORMAT:
6949 local_var_sig_token = 0;
6951 case METHOD_HEADER_FAT_FORMAT:
6955 local_var_sig_token = read32 (ptr);
6958 g_assert_not_reached ();
6961 local_var_sig_token = 0; //FIXME
6963 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6965 ret->init_locals = header->init_locals;
6966 ret->max_stack = header->max_stack;
6967 ret->local_var_sig_token = local_var_sig_token;
6968 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6969 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6972 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6973 for (i = 0; i < header->num_locals; ++i) {
6974 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6975 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6976 info->is_pinned = header->locals [i]->pinned;
6977 info->local_index = i;
6978 mono_array_setref (ret->locals, i, info);
6982 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6983 for (i = 0; i < header->num_clauses; ++i) {
6984 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6985 MonoExceptionClause *clause = &header->clauses [i];
6987 info->flags = clause->flags;
6988 info->try_offset = clause->try_offset;
6989 info->try_length = clause->try_len;
6990 info->handler_offset = clause->handler_offset;
6991 info->handler_length = clause->handler_len;
6992 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6993 info->filter_offset = clause->data.filter_offset;
6994 else if (clause->data.catch_class)
6995 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6997 mono_array_setref (ret->clauses, i, info);
7000 mono_metadata_free_mh (header);
7001 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7006 * mono_get_dbnull_object:
7007 * @domain: Domain where the object lives
7009 * Returns the System.DBNull.Value singleton object
7011 * Used as the value for ParameterInfo.DefaultValue
7014 mono_get_dbnull_object (MonoDomain *domain)
7017 static MonoClassField *dbnull_value_field = NULL;
7019 if (!dbnull_value_field) {
7020 MonoClass *dbnull_klass;
7021 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7022 mono_class_init (dbnull_klass);
7023 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7024 g_assert (dbnull_value_field);
7026 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7032 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7034 guint32 param_index, i, lastp, crow = 0;
7035 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7038 MonoClass *klass = method->klass;
7039 MonoImage *image = klass->image;
7040 MonoMethodSignature *methodsig = mono_method_signature (method);
7042 MonoTableInfo *constt;
7043 MonoTableInfo *methodt;
7044 MonoTableInfo *paramt;
7046 if (!methodsig->param_count)
7049 mono_class_init (klass);
7051 if (image_is_dynamic (klass->image)) {
7052 MonoReflectionMethodAux *aux;
7053 if (method->is_inflated)
7054 method = ((MonoMethodInflated*)method)->declaring;
7055 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7056 if (aux && aux->param_defaults) {
7057 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7058 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7063 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7064 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7065 constt = &image->tables [MONO_TABLE_CONSTANT];
7067 idx = mono_method_get_index (method) - 1;
7068 g_assert (idx != -1);
7070 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7071 if (idx + 1 < methodt->rows)
7072 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7074 lastp = paramt->rows + 1;
7076 for (i = param_index; i < lastp; ++i) {
7079 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7080 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7082 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7085 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7090 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7091 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7092 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7099 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7104 MonoType *basetype = type;
7109 klass = mono_class_from_mono_type (type);
7110 if (klass->valuetype) {
7111 object = mono_object_new (domain, klass);
7112 retval = ((gchar *) object + sizeof (MonoObject));
7113 if (klass->enumtype)
7114 basetype = mono_class_enum_basetype (klass);
7119 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7126 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7129 gboolean quoted = FALSE;
7131 memset (assembly, 0, sizeof (MonoAssemblyName));
7132 assembly->culture = "";
7133 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7140 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7151 /* Remove trailing whitespace */
7153 while (*s && g_ascii_isspace (*s))
7156 while (g_ascii_isspace (*p))
7159 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7161 assembly->major = strtoul (p, &s, 10);
7162 if (s == p || *s != '.')
7165 assembly->minor = strtoul (p, &s, 10);
7166 if (s == p || *s != '.')
7169 assembly->build = strtoul (p, &s, 10);
7170 if (s == p || *s != '.')
7173 assembly->revision = strtoul (p, &s, 10);
7177 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7179 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7180 assembly->culture = "";
7183 assembly->culture = p;
7184 while (*p && *p != ',') {
7188 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7190 if (strncmp (p, "null", 4) == 0) {
7195 while (*p && *p != ',') {
7198 len = (p - start + 1);
7199 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7200 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7201 g_strlcpy ((char*)assembly->public_key_token, start, len);
7204 while (*p && *p != ',')
7208 while (g_ascii_isspace (*p) || *p == ',') {
7222 * mono_reflection_parse_type:
7225 * Parse a type name as accepted by the GetType () method and output the info
7226 * extracted in the info structure.
7227 * the name param will be mangled, so, make a copy before passing it to this function.
7228 * The fields in info will be valid until the memory pointed to by name is valid.
7230 * See also mono_type_get_name () below.
7232 * Returns: 0 on parse error.
7235 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7236 MonoTypeNameParse *info)
7238 char *start, *p, *w, *last_point, *startn;
7239 int in_modifiers = 0;
7240 int isbyref = 0, rank = 0;
7242 start = p = w = name;
7244 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7245 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7246 info->name = info->name_space = NULL;
7247 info->nested = NULL;
7248 info->modifiers = NULL;
7249 info->type_arguments = NULL;
7251 /* last_point separates the namespace from the name */
7254 while (*p == ' ') p++, start++, w++, name++;
7259 *p = 0; /* NULL terminate the name */
7261 info->nested = g_list_append (info->nested, startn);
7262 /* we have parsed the nesting namespace + name */
7266 info->name_space = start;
7268 info->name = last_point + 1;
7270 info->name_space = (char *)"";
7298 info->name_space = start;
7300 info->name = last_point + 1;
7302 info->name_space = (char *)"";
7309 if (isbyref) /* only one level allowed by the spec */
7312 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7316 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7320 //Decide if it's an array of a generic argument list
7325 if (*p == ',' || *p == '*' || *p == ']') { //array
7332 else if (*p == '*') /* '*' means unknown lower bound */
7333 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7340 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7342 if (rank) /* generic args after array spec*/ //XXX test
7344 info->type_arguments = g_ptr_array_new ();
7346 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7347 gboolean fqname = FALSE;
7349 g_ptr_array_add (info->type_arguments, subinfo);
7351 while (*p == ' ') p++;
7357 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7360 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7361 if (fqname && (*p != ']')) {
7369 while (*p && (*p != ']'))
7377 if (g_ascii_isspace (*aname)) {
7384 !assembly_name_to_aname (&subinfo->assembly, aname))
7386 } else if (fqname && (*p == ']')) {
7408 if (g_ascii_isspace (*p)) {
7415 return 0; /* missing assembly name */
7416 if (!assembly_name_to_aname (&info->assembly, p))
7422 if (info->assembly.name)
7425 // *w = 0; /* terminate class name */
7427 if (!info->name || !*info->name)
7431 /* add other consistency checks */
7436 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7438 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7442 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7444 gboolean type_resolve = FALSE;
7446 MonoImage *rootimage = image;
7448 if (info->assembly.name) {
7449 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7450 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7452 * This could happen in the AOT compiler case when the search hook is not
7455 assembly = image->assembly;
7457 /* then we must load the assembly ourselve - see #60439 */
7458 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7462 image = assembly->image;
7463 } else if (!image) {
7464 image = mono_defaults.corlib;
7467 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7468 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7469 image = mono_defaults.corlib;
7470 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7477 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7482 gboolean bounded = FALSE;
7485 image = mono_defaults.corlib;
7489 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7490 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7492 klass = mono_class_from_name (image, info->name_space, info->name);
7496 for (mod = info->nested; mod; mod = mod->next) {
7497 gpointer iter = NULL;
7501 mono_class_init (parent);
7503 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7505 char *nested_name, *nested_nspace;
7506 gboolean match = TRUE;
7508 lastp = strrchr (mod->data, '.');
7510 /* Nested classes can have namespaces */
7513 nested_name = g_strdup (lastp + 1);
7514 nspace_len = lastp - (char*)mod->data;
7515 nested_nspace = g_malloc (nspace_len + 1);
7516 memcpy (nested_nspace, mod->data, nspace_len);
7517 nested_nspace [nspace_len] = '\0';
7520 nested_name = mod->data;
7521 nested_nspace = NULL;
7524 if (nested_nspace) {
7526 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7529 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7535 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7538 if (strcmp (klass->name, nested_name) != 0)
7543 g_free (nested_name);
7544 g_free (nested_nspace);
7556 if (info->type_arguments) {
7557 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7558 MonoReflectionType *the_type;
7562 for (i = 0; i < info->type_arguments->len; i++) {
7563 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7565 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7566 if (!type_args [i]) {
7572 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7574 instance = mono_reflection_bind_generic_parameters (
7575 the_type, info->type_arguments->len, type_args);
7581 klass = mono_class_from_mono_type (instance);
7584 for (mod = info->modifiers; mod; mod = mod->next) {
7585 modval = GPOINTER_TO_UINT (mod->data);
7586 if (!modval) { /* byref: must be last modifier */
7587 return &klass->this_arg;
7588 } else if (modval == -1) {
7589 klass = mono_ptr_class_get (&klass->byval_arg);
7590 } else if (modval == -2) {
7592 } else { /* array rank */
7593 klass = mono_bounded_array_class_get (klass, modval, bounded);
7597 return &klass->byval_arg;
7601 * mono_reflection_get_type:
7602 * @image: a metadata context
7603 * @info: type description structure
7604 * @ignorecase: flag for case-insensitive string compares
7605 * @type_resolve: whenever type resolve was already tried
7607 * Build a MonoType from the type description in @info.
7612 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7613 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7617 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7619 MonoReflectionAssemblyBuilder *abuilder;
7623 g_assert (assembly_is_dynamic (assembly));
7624 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7626 /* Enumerate all modules */
7629 if (abuilder->modules) {
7630 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7631 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7632 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7638 if (!type && abuilder->loaded_modules) {
7639 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7640 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7641 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7651 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7654 MonoReflectionAssembly *assembly;
7658 if (image && image_is_dynamic (image))
7659 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7661 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7664 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7671 *type_resolve = TRUE;
7674 /* Reconstruct the type name */
7675 fullName = g_string_new ("");
7676 if (info->name_space && (info->name_space [0] != '\0'))
7677 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7679 g_string_printf (fullName, "%s", info->name);
7680 for (mod = info->nested; mod; mod = mod->next)
7681 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7683 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7685 if (assembly_is_dynamic (assembly->assembly))
7686 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7688 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7691 g_string_free (fullName, TRUE);
7696 mono_reflection_free_type_info (MonoTypeNameParse *info)
7698 g_list_free (info->modifiers);
7699 g_list_free (info->nested);
7701 if (info->type_arguments) {
7704 for (i = 0; i < info->type_arguments->len; i++) {
7705 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7707 mono_reflection_free_type_info (subinfo);
7708 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7712 g_ptr_array_free (info->type_arguments, TRUE);
7717 * mono_reflection_type_from_name:
7719 * @image: a metadata context (can be NULL).
7721 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7722 * it defaults to get the type from @image or, if @image is NULL or loading
7723 * from it fails, uses corlib.
7727 mono_reflection_type_from_name (char *name, MonoImage *image)
7729 MonoType *type = NULL;
7730 MonoTypeNameParse info;
7733 /* Make a copy since parse_type modifies its argument */
7734 tmp = g_strdup (name);
7736 /*g_print ("requested type %s\n", str);*/
7737 if (mono_reflection_parse_type (tmp, &info)) {
7738 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7742 mono_reflection_free_type_info (&info);
7747 * mono_reflection_get_token:
7749 * Return the metadata token of OBJ which should be an object
7750 * representing a metadata element.
7753 mono_reflection_get_token (MonoObject *obj)
7758 klass = obj->vtable->klass;
7760 if (strcmp (klass->name, "MethodBuilder") == 0) {
7761 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7763 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7764 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7765 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7767 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7768 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7769 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7771 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7772 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7773 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7774 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7775 } else if (strcmp (klass->name, "MonoType") == 0) {
7776 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7777 MonoClass *mc = mono_class_from_mono_type (type);
7778 if (!mono_class_init (mc))
7779 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7781 token = mc->type_token;
7782 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7783 strcmp (klass->name, "MonoMethod") == 0 ||
7784 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7785 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7786 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7787 if (m->method->is_inflated) {
7788 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7789 return inflated->declaring->token;
7791 token = m->method->token;
7793 } else if (strcmp (klass->name, "MonoField") == 0) {
7794 MonoReflectionField *f = (MonoReflectionField*)obj;
7796 if (is_field_on_inst (f->field)) {
7797 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7799 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7800 int field_index = f->field - dgclass->fields;
7803 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7804 obj = dgclass->field_objects [field_index];
7805 return mono_reflection_get_token (obj);
7808 token = mono_class_get_field_token (f->field);
7809 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7810 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7812 token = mono_class_get_property_token (p->property);
7813 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7814 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7816 token = mono_class_get_event_token (p->event);
7817 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7818 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7819 MonoClass *member_class = mono_object_class (p->MemberImpl);
7820 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7822 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7823 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7824 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7827 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7828 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7830 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7831 MonoException *ex = mono_get_exception_not_implemented (msg);
7833 mono_raise_exception (ex);
7840 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7844 int slen = mono_metadata_decode_value (p, &p);
7846 mono_error_init (error);
7848 n = g_memdup (p, slen + 1);
7850 t = mono_reflection_type_from_name (n, image);
7852 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7853 /* We don't free n, it's consumed by mono_error */
7854 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7860 return mono_class_from_mono_type (t);
7864 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7866 int slen, type = t->type;
7867 MonoClass *tklass = t->data.klass;
7869 mono_error_init (error);
7875 case MONO_TYPE_BOOLEAN: {
7876 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7881 case MONO_TYPE_CHAR:
7883 case MONO_TYPE_I2: {
7884 guint16 *val = g_malloc (sizeof (guint16));
7889 #if SIZEOF_VOID_P == 4
7895 case MONO_TYPE_I4: {
7896 guint32 *val = g_malloc (sizeof (guint32));
7901 #if SIZEOF_VOID_P == 8
7902 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7906 case MONO_TYPE_I8: {
7907 guint64 *val = g_malloc (sizeof (guint64));
7912 case MONO_TYPE_R8: {
7913 double *val = g_malloc (sizeof (double));
7918 case MONO_TYPE_VALUETYPE:
7919 if (t->data.klass->enumtype) {
7920 type = mono_class_enum_basetype (t->data.klass)->type;
7923 MonoClass *k = t->data.klass;
7925 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7926 guint64 *val = g_malloc (sizeof (guint64));
7932 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7935 case MONO_TYPE_STRING:
7936 if (*p == (char)0xFF) {
7940 slen = mono_metadata_decode_value (p, &p);
7942 return mono_string_new_len (mono_domain_get (), p, slen);
7943 case MONO_TYPE_CLASS: {
7946 if (*p == (char)0xFF) {
7951 slen = mono_metadata_decode_value (p, &p);
7952 n = g_memdup (p, slen + 1);
7954 t = mono_reflection_type_from_name (n, image);
7956 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7957 /* We don't free n, it's consumed by mono_error */
7958 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7963 return mono_type_get_object (mono_domain_get (), t);
7965 case MONO_TYPE_OBJECT: {
7968 MonoClass *subc = NULL;
7973 } else if (subt == 0x0E) {
7974 type = MONO_TYPE_STRING;
7976 } else if (subt == 0x1D) {
7977 MonoType simple_type = {{0}};
7981 type = MONO_TYPE_SZARRAY;
7982 if (etype == 0x50) {
7983 tklass = mono_defaults.systemtype_class;
7984 } else if (etype == 0x55) {
7985 tklass = load_cattr_enum_type (image, p, &p, error);
7986 if (!mono_error_ok (error))
7990 /* See Partition II, Appendix B3 */
7991 etype = MONO_TYPE_OBJECT;
7992 simple_type.type = etype;
7993 tklass = mono_class_from_mono_type (&simple_type);
7996 } else if (subt == 0x55) {
7999 slen = mono_metadata_decode_value (p, &p);
8000 n = g_memdup (p, slen + 1);
8002 t = mono_reflection_type_from_name (n, image);
8004 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8005 /* We don't free n, it's consumed by mono_error */
8006 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8011 subc = mono_class_from_mono_type (t);
8012 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8013 MonoType simple_type = {{0}};
8014 simple_type.type = subt;
8015 subc = mono_class_from_mono_type (&simple_type);
8017 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8019 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8021 if (mono_error_ok (error)) {
8022 obj = mono_object_new (mono_domain_get (), subc);
8023 g_assert (!subc->has_references);
8024 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8030 case MONO_TYPE_SZARRAY: {
8032 guint32 i, alen, basetype;
8035 if (alen == 0xffffffff) {
8039 arr = mono_array_new (mono_domain_get(), tklass, alen);
8040 basetype = tklass->byval_arg.type;
8041 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8042 basetype = mono_class_enum_basetype (tklass)->type;
8047 case MONO_TYPE_BOOLEAN:
8048 for (i = 0; i < alen; i++) {
8049 MonoBoolean val = *p++;
8050 mono_array_set (arr, MonoBoolean, i, val);
8053 case MONO_TYPE_CHAR:
8056 for (i = 0; i < alen; i++) {
8057 guint16 val = read16 (p);
8058 mono_array_set (arr, guint16, i, val);
8065 for (i = 0; i < alen; i++) {
8066 guint32 val = read32 (p);
8067 mono_array_set (arr, guint32, i, val);
8072 for (i = 0; i < alen; i++) {
8075 mono_array_set (arr, double, i, val);
8081 for (i = 0; i < alen; i++) {
8082 guint64 val = read64 (p);
8083 mono_array_set (arr, guint64, i, val);
8087 case MONO_TYPE_CLASS:
8088 case MONO_TYPE_OBJECT:
8089 case MONO_TYPE_STRING:
8090 case MONO_TYPE_SZARRAY:
8091 for (i = 0; i < alen; i++) {
8092 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8093 if (!mono_error_ok (error))
8095 mono_array_setref (arr, i, item);
8099 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8105 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8111 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8113 static MonoClass *klass;
8114 static MonoMethod *ctor;
8116 void *params [2], *unboxed;
8119 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8121 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8123 params [0] = mono_type_get_object (mono_domain_get (), t);
8125 retval = mono_object_new (mono_domain_get (), klass);
8126 unboxed = mono_object_unbox (retval);
8127 mono_runtime_invoke (ctor, unboxed, params, NULL);
8133 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8135 static MonoClass *klass;
8136 static MonoMethod *ctor;
8138 void *unboxed, *params [2];
8141 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8143 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8146 params [1] = typedarg;
8147 retval = mono_object_new (mono_domain_get (), klass);
8148 unboxed = mono_object_unbox (retval);
8149 mono_runtime_invoke (ctor, unboxed, params, NULL);
8155 type_is_reference (MonoType *type)
8157 switch (type->type) {
8158 case MONO_TYPE_BOOLEAN:
8159 case MONO_TYPE_CHAR:
8172 case MONO_TYPE_VALUETYPE:
8180 free_param_data (MonoMethodSignature *sig, void **params) {
8182 for (i = 0; i < sig->param_count; ++i) {
8183 if (!type_is_reference (sig->params [i]))
8184 g_free (params [i]);
8189 * Find the field index in the metadata FieldDef table.
8192 find_field_index (MonoClass *klass, MonoClassField *field) {
8195 for (i = 0; i < klass->field.count; ++i) {
8196 if (field == &klass->fields [i])
8197 return klass->field.first + 1 + i;
8203 * Find the property index in the metadata Property table.
8206 find_property_index (MonoClass *klass, MonoProperty *property) {
8209 for (i = 0; i < klass->ext->property.count; ++i) {
8210 if (property == &klass->ext->properties [i])
8211 return klass->ext->property.first + 1 + i;
8217 * Find the event index in the metadata Event table.
8220 find_event_index (MonoClass *klass, MonoEvent *event) {
8223 for (i = 0; i < klass->ext->event.count; ++i) {
8224 if (event == &klass->ext->events [i])
8225 return klass->ext->event.first + 1 + i;
8231 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8233 const char *p = (const char*)data;
8235 guint32 i, j, num_named;
8237 void *params_buf [32];
8238 void **params = NULL;
8239 MonoMethodSignature *sig;
8240 MonoObject *exc = NULL;
8242 mono_error_init (error);
8244 mono_class_init (method->klass);
8246 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8247 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8252 attr = mono_object_new (mono_domain_get (), method->klass);
8253 mono_runtime_invoke (method, attr, NULL, NULL);
8257 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8260 /*g_print ("got attr %s\n", method->klass->name);*/
8262 sig = mono_method_signature (method);
8263 if (sig->param_count < 32) {
8264 params = params_buf;
8265 memset (params, 0, sizeof (void*) * sig->param_count);
8267 /* Allocate using GC so it gets GC tracking */
8268 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8273 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8274 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8275 if (!mono_error_ok (error))
8280 attr = mono_object_new (mono_domain_get (), method->klass);
8282 mono_runtime_invoke (method, attr, params, &exc);
8285 num_named = read16 (named);
8287 for (j = 0; j < num_named; j++) {
8289 char *name, named_type, data_type;
8290 named_type = *named++;
8291 data_type = *named++; /* type of data */
8292 if (data_type == MONO_TYPE_SZARRAY)
8293 data_type = *named++;
8294 if (data_type == MONO_TYPE_ENUM) {
8297 type_len = mono_metadata_decode_blob_size (named, &named);
8298 type_name = g_malloc (type_len + 1);
8299 memcpy (type_name, named, type_len);
8300 type_name [type_len] = 0;
8302 /* FIXME: lookup the type and check type consistency */
8305 name_len = mono_metadata_decode_blob_size (named, &named);
8306 name = g_malloc (name_len + 1);
8307 memcpy (name, named, name_len);
8308 name [name_len] = 0;
8310 if (named_type == 0x53) {
8311 MonoClassField *field;
8314 /* how this fail is a blackbox */
8315 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8317 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8322 val = load_cattr_value (image, field->type, named, &named, error);
8323 if (!mono_error_ok (error)) {
8325 if (!type_is_reference (field->type))
8330 mono_field_set_value (attr, field, val);
8331 if (!type_is_reference (field->type))
8333 } else if (named_type == 0x54) {
8336 MonoType *prop_type;
8338 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8341 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8347 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8352 /* can we have more that 1 arg in a custom attr named property? */
8353 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8354 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8356 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8357 if (!mono_error_ok (error)) {
8359 if (!type_is_reference (prop_type))
8360 g_free (pparams [0]);
8365 mono_property_set_value (prop, attr, pparams, NULL);
8366 if (!type_is_reference (prop_type))
8367 g_free (pparams [0]);
8372 free_param_data (method->signature, params);
8373 if (params != params_buf)
8374 mono_gc_free_fixed (params);
8379 free_param_data (method->signature, params);
8380 if (params != params_buf)
8381 mono_gc_free_fixed (params);
8383 mono_raise_exception ((MonoException*)exc);
8388 * mono_reflection_create_custom_attr_data_args:
8390 * Create an array of typed and named arguments from the cattr blob given by DATA.
8391 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8392 * NAMED_ARG_INFO will contain information about the named arguments.
8395 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)
8397 MonoArray *typedargs, *namedargs;
8398 MonoClass *attrklass;
8400 const char *p = (const char*)data;
8402 guint32 i, j, num_named;
8403 CattrNamedArg *arginfo = NULL;
8407 *named_arg_info = NULL;
8409 mono_error_init (error);
8411 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8412 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8416 mono_class_init (method->klass);
8418 domain = mono_domain_get ();
8420 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8423 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8427 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8431 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8432 if (!mono_error_ok (error)) {
8433 if (!type_is_reference (mono_method_signature (method)->params [i]))
8438 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8439 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8440 mono_array_setref (typedargs, i, obj);
8442 if (!type_is_reference (mono_method_signature (method)->params [i]))
8447 num_named = read16 (named);
8448 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8450 attrklass = method->klass;
8452 arginfo = g_new0 (CattrNamedArg, num_named);
8453 *named_arg_info = arginfo;
8455 for (j = 0; j < num_named; j++) {
8457 char *name, named_type, data_type;
8458 named_type = *named++;
8459 data_type = *named++; /* type of data */
8460 if (data_type == MONO_TYPE_SZARRAY)
8461 data_type = *named++;
8462 if (data_type == MONO_TYPE_ENUM) {
8465 type_len = mono_metadata_decode_blob_size (named, &named);
8466 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8469 type_name = g_malloc (type_len + 1);
8470 memcpy (type_name, named, type_len);
8471 type_name [type_len] = 0;
8473 /* FIXME: lookup the type and check type consistency */
8476 name_len = mono_metadata_decode_blob_size (named, &named);
8477 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8479 name = g_malloc (name_len + 1);
8480 memcpy (name, named, name_len);
8481 name [name_len] = 0;
8483 if (named_type == 0x53) {
8485 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8493 arginfo [j].type = field->type;
8494 arginfo [j].field = field;
8496 val = load_cattr_value (image, field->type, named, &named, error);
8497 if (!mono_error_ok (error)) {
8498 if (!type_is_reference (field->type))
8504 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8505 mono_array_setref (namedargs, j, obj);
8506 if (!type_is_reference (field->type))
8508 } else if (named_type == 0x54) {
8510 MonoType *prop_type;
8511 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8514 if (!prop || !prop->set) {
8519 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8520 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8522 arginfo [j].type = prop_type;
8523 arginfo [j].prop = prop;
8525 val = load_cattr_value (image, prop_type, named, &named, error);
8526 if (!mono_error_ok (error)) {
8527 if (!type_is_reference (prop_type))
8533 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8534 mono_array_setref (namedargs, j, obj);
8535 if (!type_is_reference (prop_type))
8541 *typed_args = typedargs;
8542 *named_args = namedargs;
8545 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8547 *named_arg_info = NULL;
8551 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8554 MonoArray *typedargs, *namedargs;
8557 CattrNamedArg *arginfo = NULL;
8567 image = assembly->assembly->image;
8568 method = ref_method->method;
8569 domain = mono_object_domain (ref_method);
8571 if (!mono_class_init (method->klass))
8572 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8574 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8575 if (!mono_error_ok (&error))
8576 mono_error_raise_exception (&error);
8577 if (mono_loader_get_last_error ())
8578 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8580 if (!typedargs || !namedargs) {
8585 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8586 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8587 MonoObject *typedarg;
8589 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8590 mono_array_setref (typedargs, i, typedarg);
8593 for (i = 0; i < mono_array_length (namedargs); ++i) {
8594 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8595 MonoObject *typedarg, *namedarg, *minfo;
8597 if (arginfo [i].prop)
8598 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8600 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8602 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8603 namedarg = create_cattr_named_arg (minfo, typedarg);
8605 mono_array_setref (namedargs, i, namedarg);
8608 *ctor_args = typedargs;
8609 *named_args = namedargs;
8614 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8616 static MonoMethod *ctor;
8621 g_assert (image->assembly);
8624 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8626 domain = mono_domain_get ();
8627 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8628 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8629 params [1] = mono_assembly_get_object (domain, image->assembly);
8630 params [2] = (gpointer)&cattr->data;
8631 params [3] = &cattr->data_size;
8632 mono_runtime_invoke (ctor, attr, params, NULL);
8637 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8643 mono_error_init (error);
8646 for (i = 0; i < cinfo->num_attrs; ++i) {
8647 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8651 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8653 for (i = 0; i < cinfo->num_attrs; ++i) {
8654 if (!cinfo->attrs [i].ctor)
8655 /* The cattr type is not finished yet */
8656 /* We should include the type name but cinfo doesn't contain it */
8657 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8658 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8659 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8660 if (!mono_error_ok (error))
8662 mono_array_setref (result, n, attr);
8670 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8673 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8674 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8680 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8686 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8687 for (i = 0; i < cinfo->num_attrs; ++i) {
8688 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8689 mono_array_setref (result, i, attr);
8695 * mono_custom_attrs_from_index:
8697 * Returns: NULL if no attributes are found or if a loading error occurs.
8700 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8702 guint32 mtoken, i, len;
8703 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8705 MonoCustomAttrInfo *ainfo;
8706 GList *tmp, *list = NULL;
8709 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8711 i = mono_metadata_custom_attrs_from_index (image, idx);
8715 while (i < ca->rows) {
8716 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8718 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8721 len = g_list_length (list);
8724 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8725 ainfo->num_attrs = len;
8726 ainfo->image = image;
8727 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8728 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8729 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8730 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8731 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8732 mtoken |= MONO_TOKEN_METHOD_DEF;
8734 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8735 mtoken |= MONO_TOKEN_MEMBER_REF;
8738 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8741 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8742 if (!ainfo->attrs [i].ctor) {
8743 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8749 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8750 /*FIXME raising an exception here doesn't make any sense*/
8751 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8756 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8757 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8758 ainfo->attrs [i].data = (guchar*)data;
8766 mono_custom_attrs_from_method (MonoMethod *method)
8771 * An instantiated method has the same cattrs as the generic method definition.
8773 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8774 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8776 if (method->is_inflated)
8777 method = ((MonoMethodInflated *) method)->declaring;
8779 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8780 return lookup_custom_attr (method->klass->image, method);
8783 /* Synthetic methods */
8786 idx = mono_method_get_index (method);
8787 idx <<= MONO_CUSTOM_ATTR_BITS;
8788 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8789 return mono_custom_attrs_from_index (method->klass->image, idx);
8793 mono_custom_attrs_from_class (MonoClass *klass)
8797 if (klass->generic_class)
8798 klass = klass->generic_class->container_class;
8800 if (image_is_dynamic (klass->image))
8801 return lookup_custom_attr (klass->image, klass);
8803 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8804 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8805 idx <<= MONO_CUSTOM_ATTR_BITS;
8806 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8808 idx = mono_metadata_token_index (klass->type_token);
8809 idx <<= MONO_CUSTOM_ATTR_BITS;
8810 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8812 return mono_custom_attrs_from_index (klass->image, idx);
8816 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8820 if (image_is_dynamic (assembly->image))
8821 return lookup_custom_attr (assembly->image, assembly);
8822 idx = 1; /* there is only one assembly */
8823 idx <<= MONO_CUSTOM_ATTR_BITS;
8824 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8825 return mono_custom_attrs_from_index (assembly->image, idx);
8828 static MonoCustomAttrInfo*
8829 mono_custom_attrs_from_module (MonoImage *image)
8833 if (image_is_dynamic (image))
8834 return lookup_custom_attr (image, image);
8835 idx = 1; /* there is only one module */
8836 idx <<= MONO_CUSTOM_ATTR_BITS;
8837 idx |= MONO_CUSTOM_ATTR_MODULE;
8838 return mono_custom_attrs_from_index (image, idx);
8842 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8846 if (image_is_dynamic (klass->image)) {
8847 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8848 return lookup_custom_attr (klass->image, property);
8850 idx = find_property_index (klass, property);
8851 idx <<= MONO_CUSTOM_ATTR_BITS;
8852 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8853 return mono_custom_attrs_from_index (klass->image, idx);
8857 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8861 if (image_is_dynamic (klass->image)) {
8862 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8863 return lookup_custom_attr (klass->image, event);
8865 idx = find_event_index (klass, event);
8866 idx <<= MONO_CUSTOM_ATTR_BITS;
8867 idx |= MONO_CUSTOM_ATTR_EVENT;
8868 return mono_custom_attrs_from_index (klass->image, idx);
8872 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8875 if (image_is_dynamic (klass->image)) {
8876 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8877 return lookup_custom_attr (klass->image, field);
8879 idx = find_field_index (klass, field);
8880 idx <<= MONO_CUSTOM_ATTR_BITS;
8881 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8882 return mono_custom_attrs_from_index (klass->image, idx);
8886 * mono_custom_attrs_from_param:
8887 * @method: handle to the method that we want to retrieve custom parameter information from
8888 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8890 * The result must be released with mono_custom_attrs_free().
8892 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8895 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8898 guint32 i, idx, method_index;
8899 guint32 param_list, param_last, param_pos, found;
8901 MonoReflectionMethodAux *aux;
8904 * An instantiated method has the same cattrs as the generic method definition.
8906 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8907 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8909 if (method->is_inflated)
8910 method = ((MonoMethodInflated *) method)->declaring;
8912 if (image_is_dynamic (method->klass->image)) {
8913 MonoCustomAttrInfo *res, *ainfo;
8916 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8917 if (!aux || !aux->param_cattr)
8920 /* Need to copy since it will be freed later */
8921 ainfo = aux->param_cattr [param];
8924 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8925 res = g_malloc0 (size);
8926 memcpy (res, ainfo, size);
8930 image = method->klass->image;
8931 method_index = mono_method_get_index (method);
8934 ca = &image->tables [MONO_TABLE_METHOD];
8936 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8937 if (method_index == ca->rows) {
8938 ca = &image->tables [MONO_TABLE_PARAM];
8939 param_last = ca->rows + 1;
8941 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8942 ca = &image->tables [MONO_TABLE_PARAM];
8945 for (i = param_list; i < param_last; ++i) {
8946 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8947 if (param_pos == param) {
8955 idx <<= MONO_CUSTOM_ATTR_BITS;
8956 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8957 return mono_custom_attrs_from_index (image, idx);
8961 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8965 for (i = 0; i < ainfo->num_attrs; ++i) {
8966 klass = ainfo->attrs [i].ctor->klass;
8967 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8974 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8977 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
8978 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8983 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
8989 mono_error_init (error);
8992 for (i = 0; i < ainfo->num_attrs; ++i) {
8993 klass = ainfo->attrs [i].ctor->klass;
8994 if (mono_class_has_parent (klass, attr_klass)) {
8999 if (attr_index == -1)
9002 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9003 if (!mono_error_ok (error))
9005 return mono_array_get (attrs, MonoObject*, attr_index);
9009 * mono_reflection_get_custom_attrs_info:
9010 * @obj: a reflection object handle
9012 * Return the custom attribute info for attributes defined for the
9013 * reflection handle @obj. The objects.
9015 * FIXME this function leaks like a sieve for SRE objects.
9018 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9021 MonoCustomAttrInfo *cinfo = NULL;
9023 klass = obj->vtable->klass;
9024 if (klass == mono_defaults.monotype_class) {
9025 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9026 klass = mono_class_from_mono_type (type);
9027 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9028 cinfo = mono_custom_attrs_from_class (klass);
9029 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9030 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9031 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9032 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9033 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9034 cinfo = mono_custom_attrs_from_module (module->image);
9035 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9036 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9037 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9038 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9039 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9040 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9041 } else if (strcmp ("MonoField", klass->name) == 0) {
9042 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9043 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9044 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9045 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9046 cinfo = mono_custom_attrs_from_method (rmethod->method);
9047 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9048 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9049 cinfo = mono_custom_attrs_from_method (rmethod->method);
9050 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9051 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9052 MonoClass *member_class = mono_object_class (param->MemberImpl);
9053 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9054 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9055 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9056 } else if (is_sr_mono_property (member_class)) {
9057 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9059 if (!(method = prop->property->get))
9060 method = prop->property->set;
9063 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9065 #ifndef DISABLE_REFLECTION_EMIT
9066 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9067 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9068 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9069 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9070 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9071 MonoMethod *method = NULL;
9072 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9073 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9074 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9075 method = ((MonoReflectionMethod *)c->cb)->method;
9077 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));
9079 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9083 char *type_name = mono_type_get_full_name (member_class);
9084 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9085 MonoException *ex = mono_get_exception_not_supported (msg);
9088 mono_raise_exception (ex);
9090 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9091 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9092 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9093 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9094 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9095 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9096 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9097 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9098 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9099 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9100 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9101 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9102 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9103 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9104 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9105 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9106 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9107 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9108 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9109 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9110 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9111 } else { /* handle other types here... */
9112 g_error ("get custom attrs not yet supported for %s", klass->name);
9119 * mono_reflection_get_custom_attrs_by_type:
9120 * @obj: a reflection object handle
9122 * Return an array with all the custom attributes defined of the
9123 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9124 * of that type are returned. The objects are fully build. Return NULL if a loading error
9128 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9131 MonoCustomAttrInfo *cinfo;
9133 mono_error_init (error);
9135 cinfo = mono_reflection_get_custom_attrs_info (obj);
9137 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9139 mono_custom_attrs_free (cinfo);
9141 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9142 if (mono_loader_get_last_error ())
9144 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9151 * mono_reflection_get_custom_attrs:
9152 * @obj: a reflection object handle
9154 * Return an array with all the custom attributes defined of the
9155 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9159 mono_reflection_get_custom_attrs (MonoObject *obj)
9163 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9167 * mono_reflection_get_custom_attrs_data:
9168 * @obj: a reflection obj handle
9170 * Returns an array of System.Reflection.CustomAttributeData,
9171 * which include information about attributes reflected on
9172 * types loaded using the Reflection Only methods
9175 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9178 MonoCustomAttrInfo *cinfo;
9180 cinfo = mono_reflection_get_custom_attrs_info (obj);
9182 result = mono_custom_attrs_data_construct (cinfo);
9184 mono_custom_attrs_free (cinfo);
9186 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9191 static MonoReflectionType*
9192 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9194 static MonoMethod *method_get_underlying_system_type = NULL;
9195 MonoMethod *usertype_method;
9197 if (!method_get_underlying_system_type)
9198 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9199 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9200 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9205 is_corlib_type (MonoClass *class)
9207 return class->image == mono_defaults.corlib;
9210 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9211 static MonoClass *cached_class; \
9213 return cached_class == _class; \
9214 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9215 cached_class = _class; \
9222 #ifndef DISABLE_REFLECTION_EMIT
9224 is_sre_array (MonoClass *class)
9226 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9230 is_sre_byref (MonoClass *class)
9232 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9236 is_sre_pointer (MonoClass *class)
9238 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9242 is_sre_generic_instance (MonoClass *class)
9244 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9248 is_sre_type_builder (MonoClass *class)
9250 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9254 is_sre_method_builder (MonoClass *class)
9256 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9260 is_sre_ctor_builder (MonoClass *class)
9262 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9266 is_sre_field_builder (MonoClass *class)
9268 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9272 is_sre_method_on_tb_inst (MonoClass *class)
9274 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9278 is_sre_ctor_on_tb_inst (MonoClass *class)
9280 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9284 mono_reflection_type_get_handle (MonoReflectionType* ref)
9292 if (is_usertype (ref)) {
9293 ref = mono_reflection_type_get_underlying_system_type (ref);
9294 if (ref == NULL || is_usertype (ref))
9300 class = mono_object_class (ref);
9302 if (is_sre_array (class)) {
9304 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9305 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9307 if (sre_array->rank == 0) //single dimentional array
9308 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9310 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9311 sre_array->type.type = res;
9313 } else if (is_sre_byref (class)) {
9315 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9316 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9318 res = &mono_class_from_mono_type (base)->this_arg;
9319 sre_byref->type.type = res;
9321 } else if (is_sre_pointer (class)) {
9323 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9324 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9326 res = &mono_ptr_class_get (base)->byval_arg;
9327 sre_pointer->type.type = res;
9329 } else if (is_sre_generic_instance (class)) {
9330 MonoType *res, **types;
9331 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9334 count = mono_array_length (gclass->type_arguments);
9335 types = g_new0 (MonoType*, count);
9336 for (i = 0; i < count; ++i) {
9337 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9338 types [i] = mono_reflection_type_get_handle (t);
9345 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9348 gclass->type.type = res;
9352 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9359 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9361 mono_reflection_type_get_handle (type);
9365 mono_reflection_register_with_runtime (MonoReflectionType *type)
9367 MonoType *res = mono_reflection_type_get_handle (type);
9368 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9372 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9374 class = mono_class_from_mono_type (res);
9376 mono_loader_lock (); /*same locking as mono_type_get_object*/
9377 mono_domain_lock (domain);
9379 if (!image_is_dynamic (class->image)) {
9380 mono_class_setup_supertypes (class);
9382 if (!domain->type_hash)
9383 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9384 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9385 mono_g_hash_table_insert (domain->type_hash, res, type);
9387 mono_domain_unlock (domain);
9388 mono_loader_unlock ();
9392 * LOCKING: Assumes the loader lock is held.
9394 static MonoMethodSignature*
9395 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9396 MonoMethodSignature *sig;
9399 count = parameters? mono_array_length (parameters): 0;
9401 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9402 sig->param_count = count;
9403 sig->sentinelpos = -1; /* FIXME */
9404 for (i = 0; i < count; ++i)
9405 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9410 * LOCKING: Assumes the loader lock is held.
9412 static MonoMethodSignature*
9413 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9414 MonoMethodSignature *sig;
9416 sig = parameters_to_signature (image, ctor->parameters);
9417 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9418 sig->ret = &mono_defaults.void_class->byval_arg;
9423 * LOCKING: Assumes the loader lock is held.
9425 static MonoMethodSignature*
9426 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9427 MonoMethodSignature *sig;
9429 sig = parameters_to_signature (image, method->parameters);
9430 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9431 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9432 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9436 static MonoMethodSignature*
9437 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9438 MonoMethodSignature *sig;
9440 sig = parameters_to_signature (NULL, method->parameters);
9441 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9442 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9443 sig->generic_param_count = 0;
9448 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9450 MonoClass *klass = mono_object_class (prop);
9451 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9452 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9453 *name = mono_string_to_utf8 (pb->name);
9454 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9456 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9457 *name = g_strdup (p->property->name);
9458 if (p->property->get)
9459 *type = mono_method_signature (p->property->get)->ret;
9461 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9466 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9468 MonoClass *klass = mono_object_class (field);
9469 if (strcmp (klass->name, "FieldBuilder") == 0) {
9470 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9471 *name = mono_string_to_utf8 (fb->name);
9472 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9474 MonoReflectionField *f = (MonoReflectionField *)field;
9475 *name = g_strdup (mono_field_get_name (f->field));
9476 *type = f->field->type;
9480 #else /* DISABLE_REFLECTION_EMIT */
9483 mono_reflection_register_with_runtime (MonoReflectionType *type)
9489 is_sre_type_builder (MonoClass *class)
9495 is_sre_generic_instance (MonoClass *class)
9501 init_type_builder_generics (MonoObject *type)
9505 #endif /* !DISABLE_REFLECTION_EMIT */
9509 is_sr_mono_field (MonoClass *class)
9511 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9515 is_sr_mono_property (MonoClass *class)
9517 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9521 is_sr_mono_method (MonoClass *class)
9523 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9527 is_sr_mono_cmethod (MonoClass *class)
9529 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9533 is_sr_mono_generic_method (MonoClass *class)
9535 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9539 is_sr_mono_generic_cmethod (MonoClass *class)
9541 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9545 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9547 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9551 is_usertype (MonoReflectionType *ref)
9553 MonoClass *class = mono_object_class (ref);
9554 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9557 static MonoReflectionType*
9558 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9560 if (!type || type->type)
9563 if (is_usertype (type)) {
9564 type = mono_reflection_type_get_underlying_system_type (type);
9565 if (is_usertype (type))
9566 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9572 * Encode a value in a custom attribute stream of bytes.
9573 * The value to encode is either supplied as an object in argument val
9574 * (valuetypes are boxed), or as a pointer to the data in the
9576 * @type represents the type of the value
9577 * @buffer is the start of the buffer
9578 * @p the current position in the buffer
9579 * @buflen contains the size of the buffer and is used to return the new buffer size
9580 * if this needs to be realloced.
9581 * @retbuffer and @retp return the start and the position of the buffer
9584 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9586 MonoTypeEnum simple_type;
9588 if ((p-buffer) + 10 >= *buflen) {
9591 newbuf = g_realloc (buffer, *buflen);
9592 p = newbuf + (p-buffer);
9596 argval = ((char*)arg + sizeof (MonoObject));
9597 simple_type = type->type;
9599 switch (simple_type) {
9600 case MONO_TYPE_BOOLEAN:
9605 case MONO_TYPE_CHAR:
9608 swap_with_size (p, argval, 2, 1);
9614 swap_with_size (p, argval, 4, 1);
9618 swap_with_size (p, argval, 8, 1);
9623 swap_with_size (p, argval, 8, 1);
9626 case MONO_TYPE_VALUETYPE:
9627 if (type->data.klass->enumtype) {
9628 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9631 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9634 case MONO_TYPE_STRING: {
9641 str = mono_string_to_utf8 ((MonoString*)arg);
9642 slen = strlen (str);
9643 if ((p-buffer) + 10 + slen >= *buflen) {
9647 newbuf = g_realloc (buffer, *buflen);
9648 p = newbuf + (p-buffer);
9651 mono_metadata_encode_value (slen, p, &p);
9652 memcpy (p, str, slen);
9657 case MONO_TYPE_CLASS: {
9665 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9666 slen = strlen (str);
9667 if ((p-buffer) + 10 + slen >= *buflen) {
9671 newbuf = g_realloc (buffer, *buflen);
9672 p = newbuf + (p-buffer);
9675 mono_metadata_encode_value (slen, p, &p);
9676 memcpy (p, str, slen);
9681 case MONO_TYPE_SZARRAY: {
9683 MonoClass *eclass, *arg_eclass;
9686 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9689 len = mono_array_length ((MonoArray*)arg);
9691 *p++ = (len >> 8) & 0xff;
9692 *p++ = (len >> 16) & 0xff;
9693 *p++ = (len >> 24) & 0xff;
9695 *retbuffer = buffer;
9696 eclass = type->data.klass;
9697 arg_eclass = mono_object_class (arg)->element_class;
9700 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9701 eclass = mono_defaults.object_class;
9703 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9704 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9705 int elsize = mono_class_array_element_size (arg_eclass);
9706 for (i = 0; i < len; ++i) {
9707 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9710 } else if (eclass->valuetype && arg_eclass->valuetype) {
9711 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9712 int elsize = mono_class_array_element_size (eclass);
9713 for (i = 0; i < len; ++i) {
9714 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9718 for (i = 0; i < len; ++i) {
9719 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9724 case MONO_TYPE_OBJECT: {
9730 * The parameter type is 'object' but the type of the actual
9731 * argument is not. So we have to add type information to the blob
9732 * too. This is completely undocumented in the spec.
9736 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9741 klass = mono_object_class (arg);
9743 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9746 } else if (klass->enumtype) {
9748 } else if (klass == mono_defaults.string_class) {
9749 simple_type = MONO_TYPE_STRING;
9752 } else if (klass->rank == 1) {
9754 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9755 /* See Partition II, Appendix B3 */
9758 *p++ = klass->element_class->byval_arg.type;
9759 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9761 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9762 *p++ = simple_type = klass->byval_arg.type;
9765 g_error ("unhandled type in custom attr");
9767 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9768 slen = strlen (str);
9769 if ((p-buffer) + 10 + slen >= *buflen) {
9773 newbuf = g_realloc (buffer, *buflen);
9774 p = newbuf + (p-buffer);
9777 mono_metadata_encode_value (slen, p, &p);
9778 memcpy (p, str, slen);
9781 simple_type = mono_class_enum_basetype (klass)->type;
9785 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9788 *retbuffer = buffer;
9792 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9794 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9795 char *str = type_get_qualified_name (type, NULL);
9796 int slen = strlen (str);
9800 * This seems to be optional...
9803 mono_metadata_encode_value (slen, p, &p);
9804 memcpy (p, str, slen);
9807 } else if (type->type == MONO_TYPE_OBJECT) {
9809 } else if (type->type == MONO_TYPE_CLASS) {
9810 /* it should be a type: encode_cattr_value () has the check */
9813 mono_metadata_encode_value (type->type, p, &p);
9814 if (type->type == MONO_TYPE_SZARRAY)
9815 /* See the examples in Partition VI, Annex B */
9816 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9822 #ifndef DISABLE_REFLECTION_EMIT
9824 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9827 /* Preallocate a large enough buffer */
9828 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9829 char *str = type_get_qualified_name (type, NULL);
9832 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9833 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9839 len += strlen (name);
9841 if ((p-buffer) + 20 + len >= *buflen) {
9845 newbuf = g_realloc (buffer, *buflen);
9846 p = newbuf + (p-buffer);
9850 encode_field_or_prop_type (type, p, &p);
9852 len = strlen (name);
9853 mono_metadata_encode_value (len, p, &p);
9854 memcpy (p, name, len);
9856 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9858 *retbuffer = buffer;
9862 * mono_reflection_get_custom_attrs_blob:
9863 * @ctor: custom attribute constructor
9864 * @ctorArgs: arguments o the constructor
9870 * Creates the blob of data that needs to be saved in the metadata and that represents
9871 * the custom attributed described by @ctor, @ctorArgs etc.
9872 * Returns: a Byte array representing the blob of data.
9875 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9878 MonoMethodSignature *sig;
9883 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9884 /* sig is freed later so allocate it in the heap */
9885 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9887 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9890 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9892 p = buffer = g_malloc (buflen);
9893 /* write the prolog */
9896 for (i = 0; i < sig->param_count; ++i) {
9897 arg = mono_array_get (ctorArgs, MonoObject*, i);
9898 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9902 i += mono_array_length (properties);
9904 i += mono_array_length (fields);
9906 *p++ = (i >> 8) & 0xff;
9909 for (i = 0; i < mono_array_length (properties); ++i) {
9913 prop = mono_array_get (properties, gpointer, i);
9914 get_prop_name_and_type (prop, &pname, &ptype);
9915 *p++ = 0x54; /* PROPERTY signature */
9916 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9923 for (i = 0; i < mono_array_length (fields); ++i) {
9927 field = mono_array_get (fields, gpointer, i);
9928 get_field_name_and_type (field, &fname, &ftype);
9929 *p++ = 0x53; /* FIELD signature */
9930 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9935 g_assert (p - buffer <= buflen);
9936 buflen = p - buffer;
9937 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9938 p = mono_array_addr (result, char, 0);
9939 memcpy (p, buffer, buflen);
9941 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9947 * mono_reflection_setup_internal_class:
9948 * @tb: a TypeBuilder object
9950 * Creates a MonoClass that represents the TypeBuilder.
9951 * This is a trick that lets us simplify a lot of reflection code
9952 * (and will allow us to support Build and Run assemblies easier).
9955 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9958 MonoClass *klass, *parent;
9960 RESOLVE_TYPE (tb->parent);
9962 mono_loader_lock ();
9965 /* check so we can compile corlib correctly */
9966 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9967 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9968 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9970 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9976 /* the type has already being created: it means we just have to change the parent */
9977 if (tb->type.type) {
9978 klass = mono_class_from_mono_type (tb->type.type);
9979 klass->parent = NULL;
9980 /* fool mono_class_setup_parent */
9981 klass->supertypes = NULL;
9982 mono_class_setup_parent (klass, parent);
9983 mono_class_setup_mono_type (klass);
9984 mono_loader_unlock ();
9988 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9990 klass->image = &tb->module->dynamic_image->image;
9992 klass->inited = 1; /* we lie to the runtime */
9993 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9994 if (!mono_error_ok (&error))
9996 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9997 if (!mono_error_ok (&error))
9999 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10000 klass->flags = tb->attrs;
10002 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10004 klass->element_class = klass;
10006 if (mono_class_get_ref_info (klass) == NULL) {
10008 mono_class_set_ref_info (klass, tb);
10010 /* Put into cache so mono_class_get_checked () will find it.
10011 Skip nested types as those should not be available on the global scope. */
10012 if (!tb->nesting_type)
10013 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10016 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10017 by performing a mono_class_get which does the full resolution.
10019 Working around this semantics would require us to write a lot of code for no clear advantage.
10021 mono_image_append_class_to_reflection_info_set (klass);
10023 g_assert (mono_class_get_ref_info (klass) == tb);
10026 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
10027 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
10029 if (parent != NULL) {
10030 mono_class_setup_parent (klass, parent);
10031 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10032 const char *old_n = klass->name;
10033 /* trick to get relative numbering right when compiling corlib */
10034 klass->name = "BuildingObject";
10035 mono_class_setup_parent (klass, mono_defaults.object_class);
10036 klass->name = old_n;
10039 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10040 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10041 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10042 klass->instance_size = sizeof (MonoObject);
10043 klass->size_inited = 1;
10044 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10047 mono_class_setup_mono_type (klass);
10049 mono_class_setup_supertypes (klass);
10052 * FIXME: handle interfaces.
10055 tb->type.type = &klass->byval_arg;
10057 if (tb->nesting_type) {
10058 g_assert (tb->nesting_type->type);
10059 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10062 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10064 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10066 mono_loader_unlock ();
10070 mono_loader_unlock ();
10071 mono_error_raise_exception (&error);
10075 * mono_reflection_setup_generic_class:
10076 * @tb: a TypeBuilder object
10078 * Setup the generic class before adding the first generic parameter.
10081 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10086 * mono_reflection_create_generic_class:
10087 * @tb: a TypeBuilder object
10089 * Creates the generic class after all generic parameters have been added.
10092 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10097 klass = mono_class_from_mono_type (tb->type.type);
10099 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10101 if (klass->generic_container || (count == 0))
10104 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10106 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10108 klass->generic_container->owner.klass = klass;
10109 klass->generic_container->type_argc = count;
10110 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10112 klass->is_generic = 1;
10114 for (i = 0; i < count; i++) {
10115 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10116 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10117 klass->generic_container->type_params [i] = *param;
10118 /*Make sure we are a diferent type instance */
10119 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10120 klass->generic_container->type_params [i].info.pklass = NULL;
10121 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10123 g_assert (klass->generic_container->type_params [i].param.owner);
10126 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10130 * mono_reflection_create_internal_class:
10131 * @tb: a TypeBuilder object
10133 * Actually create the MonoClass that is associated with the TypeBuilder.
10136 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10140 klass = mono_class_from_mono_type (tb->type.type);
10142 mono_loader_lock ();
10143 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10144 MonoReflectionFieldBuilder *fb;
10146 MonoType *enum_basetype;
10148 g_assert (tb->fields != NULL);
10149 g_assert (mono_array_length (tb->fields) >= 1);
10151 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10153 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10154 mono_loader_unlock ();
10158 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10159 klass->element_class = mono_class_from_mono_type (enum_basetype);
10160 if (!klass->element_class)
10161 klass->element_class = mono_class_from_mono_type (enum_basetype);
10164 * get the element_class from the current corlib.
10166 ec = default_class_from_mono_type (enum_basetype);
10167 klass->instance_size = ec->instance_size;
10168 klass->size_inited = 1;
10170 * this is almost safe to do with enums and it's needed to be able
10171 * to create objects of the enum type (for use in SetConstant).
10173 /* FIXME: Does this mean enums can't have method overrides ? */
10174 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10176 mono_loader_unlock ();
10179 static MonoMarshalSpec*
10180 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10181 MonoReflectionMarshal *minfo)
10183 MonoMarshalSpec *res;
10185 res = image_g_new0 (image, MonoMarshalSpec, 1);
10186 res->native = minfo->type;
10188 switch (minfo->type) {
10189 case MONO_NATIVE_LPARRAY:
10190 res->data.array_data.elem_type = minfo->eltype;
10191 if (minfo->has_size) {
10192 res->data.array_data.param_num = minfo->param_num;
10193 res->data.array_data.num_elem = minfo->count;
10194 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10197 res->data.array_data.param_num = -1;
10198 res->data.array_data.num_elem = -1;
10199 res->data.array_data.elem_mult = -1;
10203 case MONO_NATIVE_BYVALTSTR:
10204 case MONO_NATIVE_BYVALARRAY:
10205 res->data.array_data.num_elem = minfo->count;
10208 case MONO_NATIVE_CUSTOM:
10209 if (minfo->marshaltyperef)
10210 res->data.custom_data.custom_name =
10211 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10212 if (minfo->mcookie)
10213 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10222 #endif /* !DISABLE_REFLECTION_EMIT */
10224 MonoReflectionMarshalAsAttribute*
10225 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10226 MonoMarshalSpec *spec)
10228 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10229 MonoReflectionMarshalAsAttribute *minfo;
10232 if (!System_Reflection_Emit_MarshalAsAttribute) {
10233 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10234 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10235 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10238 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10239 minfo->utype = spec->native;
10241 switch (minfo->utype) {
10242 case MONO_NATIVE_LPARRAY:
10243 minfo->array_subtype = spec->data.array_data.elem_type;
10244 minfo->size_const = spec->data.array_data.num_elem;
10245 if (spec->data.array_data.param_num != -1)
10246 minfo->size_param_index = spec->data.array_data.param_num;
10249 case MONO_NATIVE_BYVALTSTR:
10250 case MONO_NATIVE_BYVALARRAY:
10251 minfo->size_const = spec->data.array_data.num_elem;
10254 case MONO_NATIVE_CUSTOM:
10255 if (spec->data.custom_data.custom_name) {
10256 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10258 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10260 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10262 if (spec->data.custom_data.cookie)
10263 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10273 #ifndef DISABLE_REFLECTION_EMIT
10275 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10276 ReflectionMethodBuilder *rmb,
10277 MonoMethodSignature *sig)
10281 MonoMethodWrapper *wrapperm;
10282 MonoMarshalSpec **specs;
10283 MonoReflectionMethodAux *method_aux;
10288 mono_error_init (&error);
10290 * Methods created using a MethodBuilder should have their memory allocated
10291 * inside the image mempool, while dynamic methods should have their memory
10294 dynamic = rmb->refs != NULL;
10295 image = dynamic ? NULL : klass->image;
10298 g_assert (!klass->generic_class);
10300 mono_loader_lock ();
10302 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10303 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10304 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10306 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10308 wrapperm = (MonoMethodWrapper*)m;
10310 m->dynamic = dynamic;
10312 m->flags = rmb->attrs;
10313 m->iflags = rmb->iattrs;
10314 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10316 m->signature = sig;
10317 m->sre_method = TRUE;
10318 m->skip_visibility = rmb->skip_visibility;
10319 if (rmb->table_idx)
10320 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10322 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10323 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10324 m->string_ctor = 1;
10326 m->signature->pinvoke = 1;
10327 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10328 m->signature->pinvoke = 1;
10330 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10332 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10333 g_assert (mono_error_ok (&error));
10334 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10335 g_assert (mono_error_ok (&error));
10337 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10339 if (image_is_dynamic (klass->image))
10340 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10342 mono_loader_unlock ();
10345 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10346 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10347 MonoMethodHeader *header;
10349 gint32 max_stack, i;
10350 gint32 num_locals = 0;
10351 gint32 num_clauses = 0;
10355 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10356 code_size = rmb->ilgen->code_len;
10357 max_stack = rmb->ilgen->max_stack;
10358 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10359 if (rmb->ilgen->ex_handlers)
10360 num_clauses = method_count_clauses (rmb->ilgen);
10363 code = mono_array_addr (rmb->code, guint8, 0);
10364 code_size = mono_array_length (rmb->code);
10365 /* we probably need to run a verifier on the code... */
10375 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10376 header->code_size = code_size;
10377 header->code = image_g_malloc (image, code_size);
10378 memcpy ((char*)header->code, code, code_size);
10379 header->max_stack = max_stack;
10380 header->init_locals = rmb->init_locals;
10381 header->num_locals = num_locals;
10383 for (i = 0; i < num_locals; ++i) {
10384 MonoReflectionLocalBuilder *lb =
10385 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10387 header->locals [i] = image_g_new0 (image, MonoType, 1);
10388 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10391 header->num_clauses = num_clauses;
10393 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10394 rmb->ilgen, num_clauses);
10397 wrapperm->header = header;
10400 if (rmb->generic_params) {
10401 int count = mono_array_length (rmb->generic_params);
10402 MonoGenericContainer *container = rmb->generic_container;
10404 g_assert (container);
10406 container->type_argc = count;
10407 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10408 container->owner.method = m;
10410 m->is_generic = TRUE;
10411 mono_method_set_generic_container (m, container);
10413 for (i = 0; i < count; i++) {
10414 MonoReflectionGenericParam *gp =
10415 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10416 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10417 container->type_params [i] = *param;
10421 * The method signature might have pointers to generic parameters that belong to other methods.
10422 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10423 * generic parameters.
10425 for (i = 0; i < m->signature->param_count; ++i) {
10426 MonoType *t = m->signature->params [i];
10427 if (t->type == MONO_TYPE_MVAR) {
10428 MonoGenericParam *gparam = t->data.generic_param;
10429 if (gparam->num < count) {
10430 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10431 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10437 if (klass->generic_container) {
10438 container->parent = klass->generic_container;
10439 container->context.class_inst = klass->generic_container->context.class_inst;
10441 container->context.method_inst = mono_get_shared_generic_inst (container);
10445 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10449 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10451 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10452 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10453 for (i = 0; i < rmb->nrefs; ++i)
10454 data [i + 1] = rmb->refs [i];
10459 /* Parameter info */
10462 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10463 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10464 for (i = 0; i <= m->signature->param_count; ++i) {
10465 MonoReflectionParamBuilder *pb;
10466 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10467 if ((i > 0) && (pb->attrs)) {
10468 /* Make a copy since it might point to a shared type structure */
10469 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10470 m->signature->params [i - 1]->attrs = pb->attrs;
10473 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10474 MonoDynamicImage *assembly;
10475 guint32 idx, def_type, len;
10479 if (!method_aux->param_defaults) {
10480 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10481 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10483 assembly = (MonoDynamicImage*)klass->image;
10484 idx = encode_constant (assembly, pb->def_value, &def_type);
10485 /* Copy the data from the blob since it might get realloc-ed */
10486 p = assembly->blob.data + idx;
10487 len = mono_metadata_decode_blob_size (p, &p2);
10489 method_aux->param_defaults [i] = image_g_malloc (image, len);
10490 method_aux->param_default_types [i] = def_type;
10491 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10495 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10496 g_assert (mono_error_ok (&error));
10499 if (!method_aux->param_cattr)
10500 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10501 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10507 /* Parameter marshalling */
10510 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10511 MonoReflectionParamBuilder *pb;
10512 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10513 if (pb->marshal_info) {
10515 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10516 specs [pb->position] =
10517 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10521 if (specs != NULL) {
10523 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10524 method_aux->param_marshall = specs;
10527 if (image_is_dynamic (klass->image) && method_aux)
10528 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10530 mono_loader_unlock ();
10536 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10538 ReflectionMethodBuilder rmb;
10539 MonoMethodSignature *sig;
10541 mono_loader_lock ();
10542 sig = ctor_builder_to_signature (klass->image, mb);
10543 mono_loader_unlock ();
10545 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10547 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10548 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10550 /* If we are in a generic class, we might be called multiple times from inflate_method */
10551 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10552 /* ilgen is no longer needed */
10556 return mb->mhandle;
10560 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10562 ReflectionMethodBuilder rmb;
10563 MonoMethodSignature *sig;
10565 mono_loader_lock ();
10566 sig = method_builder_to_signature (klass->image, mb);
10567 mono_loader_unlock ();
10569 reflection_methodbuilder_from_method_builder (&rmb, mb);
10571 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10572 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10574 /* If we are in a generic class, we might be called multiple times from inflate_method */
10575 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10576 /* ilgen is no longer needed */
10579 return mb->mhandle;
10582 static MonoClassField*
10583 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10585 MonoClassField *field;
10589 field = g_new0 (MonoClassField, 1);
10591 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10592 g_assert (mono_error_ok (&error));
10593 if (fb->attrs || fb->modreq || fb->modopt) {
10594 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10595 field->type->attrs = fb->attrs;
10597 g_assert (image_is_dynamic (klass->image));
10598 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10599 g_free (field->type);
10600 field->type = mono_metadata_type_dup (klass->image, custom);
10603 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10605 if (fb->offset != -1)
10606 field->offset = fb->offset;
10607 field->parent = klass;
10608 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10610 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10617 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10620 MonoReflectionTypeBuilder *tb = NULL;
10621 gboolean is_dynamic = FALSE;
10622 MonoClass *geninst;
10624 mono_loader_lock ();
10626 if (is_sre_type_builder (mono_object_class (type))) {
10627 tb = (MonoReflectionTypeBuilder *) type;
10630 } else if (is_sre_generic_instance (mono_object_class (type))) {
10631 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10632 MonoReflectionType *gtd = rgi->generic_type;
10634 if (is_sre_type_builder (mono_object_class (gtd))) {
10635 tb = (MonoReflectionTypeBuilder *)gtd;
10640 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10641 if (tb && tb->generic_container)
10642 mono_reflection_create_generic_class (tb);
10644 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10645 if (!klass->generic_container) {
10646 mono_loader_unlock ();
10650 if (klass->wastypebuilder) {
10651 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10656 mono_loader_unlock ();
10658 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10660 return &geninst->byval_arg;
10664 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10666 MonoGenericClass *gclass;
10667 MonoGenericInst *inst;
10669 g_assert (klass->generic_container);
10671 inst = mono_metadata_get_generic_inst (type_argc, types);
10672 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10674 return mono_generic_class_get_class (gclass);
10677 MonoReflectionMethod*
10678 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10682 MonoMethod *method, *inflated;
10683 MonoMethodInflated *imethod;
10684 MonoGenericContext tmp_context;
10685 MonoGenericInst *ginst;
10686 MonoType **type_argv;
10689 /*FIXME but this no longer should happen*/
10690 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10691 #ifndef DISABLE_REFLECTION_EMIT
10692 MonoReflectionMethodBuilder *mb = NULL;
10693 MonoReflectionTypeBuilder *tb;
10696 mb = (MonoReflectionMethodBuilder *) rmethod;
10697 tb = (MonoReflectionTypeBuilder *) mb->type;
10698 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10700 method = methodbuilder_to_mono_method (klass, mb);
10702 g_assert_not_reached ();
10706 method = rmethod->method;
10709 klass = method->klass;
10711 if (method->is_inflated)
10712 method = ((MonoMethodInflated *) method)->declaring;
10714 count = mono_method_signature (method)->generic_param_count;
10715 if (count != mono_array_length (types))
10718 type_argv = g_new0 (MonoType *, count);
10719 for (i = 0; i < count; i++) {
10720 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10721 type_argv [i] = mono_reflection_type_get_handle (garg);
10723 ginst = mono_metadata_get_generic_inst (count, type_argv);
10724 g_free (type_argv);
10726 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10727 tmp_context.method_inst = ginst;
10729 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10730 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10731 imethod = (MonoMethodInflated *) inflated;
10733 /*FIXME but I think this is no longer necessary*/
10734 if (image_is_dynamic (method->klass->image)) {
10735 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10737 * This table maps metadata structures representing inflated methods/fields
10738 * to the reflection objects representing their generic definitions.
10740 mono_image_lock ((MonoImage*)image);
10741 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10742 mono_image_unlock ((MonoImage*)image);
10745 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10746 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10748 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10751 #ifndef DISABLE_REFLECTION_EMIT
10753 static MonoMethod *
10754 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10756 MonoMethodInflated *imethod;
10757 MonoGenericContext *context;
10761 * With generic code sharing the klass might not be inflated.
10762 * This can happen because classes inflated with their own
10763 * type arguments are "normalized" to the uninflated class.
10765 if (!klass->generic_class)
10768 context = mono_class_get_context (klass);
10770 if (klass->method.count && klass->methods) {
10771 /* Find the already created inflated method */
10772 for (i = 0; i < klass->method.count; ++i) {
10773 g_assert (klass->methods [i]->is_inflated);
10774 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10777 g_assert (i < klass->method.count);
10778 imethod = (MonoMethodInflated*)klass->methods [i];
10781 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10782 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10785 if (method->is_generic && image_is_dynamic (method->klass->image)) {
10786 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10788 mono_image_lock ((MonoImage*)image);
10789 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10790 mono_image_unlock ((MonoImage*)image);
10792 return (MonoMethod *) imethod;
10795 static MonoMethod *
10796 inflate_method (MonoReflectionType *type, MonoObject *obj)
10798 MonoMethod *method;
10801 MonoClass *type_class = mono_object_class (type);
10803 if (is_sre_generic_instance (type_class)) {
10804 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10805 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10806 } else if (is_sre_type_builder (type_class)) {
10807 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10808 } else if (type->type) {
10809 gklass = mono_class_from_mono_type (type->type);
10810 gklass = mono_class_get_generic_type_definition (gklass);
10812 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10815 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10816 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10817 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10819 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10820 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10821 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10822 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10823 method = ((MonoReflectionMethod *) obj)->method;
10825 method = NULL; /* prevent compiler warning */
10826 g_error ("can't handle type %s", obj->vtable->klass->name);
10829 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10832 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10834 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10836 MonoGenericClass *gclass;
10837 MonoDynamicGenericClass *dgclass;
10838 MonoClass *klass, *gklass;
10842 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10843 klass = mono_class_from_mono_type (gtype);
10844 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10845 gclass = gtype->data.generic_class;
10847 if (!gclass->is_dynamic)
10850 dgclass = (MonoDynamicGenericClass *) gclass;
10852 if (dgclass->initialized)
10855 gklass = gclass->container_class;
10856 mono_class_init (gklass);
10858 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10860 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10861 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10862 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10864 for (i = 0; i < dgclass->count_fields; i++) {
10865 MonoObject *obj = mono_array_get (fields, gpointer, i);
10866 MonoClassField *field, *inflated_field = NULL;
10868 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10869 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10870 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10871 field = ((MonoReflectionField *) obj)->field;
10873 field = NULL; /* prevent compiler warning */
10874 g_assert_not_reached ();
10877 dgclass->fields [i] = *field;
10878 dgclass->fields [i].parent = klass;
10879 dgclass->fields [i].type = mono_class_inflate_generic_type (
10880 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10881 dgclass->field_generic_types [i] = field->type;
10882 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10883 dgclass->field_objects [i] = obj;
10885 if (inflated_field) {
10886 g_free (inflated_field);
10888 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10892 dgclass->initialized = TRUE;
10896 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10898 MonoDynamicGenericClass *dgclass;
10901 g_assert (gclass->is_dynamic);
10903 dgclass = (MonoDynamicGenericClass *)gclass;
10905 for (i = 0; i < dgclass->count_fields; ++i) {
10906 MonoClassField *field = dgclass->fields + i;
10907 mono_metadata_free_type (field->type);
10908 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10913 fix_partial_generic_class (MonoClass *klass)
10915 MonoClass *gklass = klass->generic_class->container_class;
10916 MonoDynamicGenericClass *dgclass;
10919 if (klass->wastypebuilder)
10922 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10923 if (klass->parent != gklass->parent) {
10925 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10926 if (mono_error_ok (&error)) {
10927 MonoClass *parent = mono_class_from_mono_type (parent_type);
10928 mono_metadata_free_type (parent_type);
10929 if (parent != klass->parent) {
10930 /*fool mono_class_setup_parent*/
10931 klass->supertypes = NULL;
10932 mono_class_setup_parent (klass, parent);
10935 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10936 mono_error_cleanup (&error);
10937 if (gklass->wastypebuilder)
10938 klass->wastypebuilder = TRUE;
10943 if (!dgclass->initialized)
10946 if (klass->method.count != gklass->method.count) {
10947 klass->method.count = gklass->method.count;
10948 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10950 for (i = 0; i < klass->method.count; i++) {
10952 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
10953 gklass->methods [i], klass, mono_class_get_context (klass), &error);
10954 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10958 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10959 klass->interface_count = gklass->interface_count;
10960 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10961 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10963 for (i = 0; i < gklass->interface_count; ++i) {
10964 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10965 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10966 mono_metadata_free_type (iface_type);
10968 ensure_runtime_vtable (klass->interfaces [i]);
10970 klass->interfaces_inited = 1;
10973 if (klass->field.count != gklass->field.count) {
10974 klass->field.count = gklass->field.count;
10975 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10977 for (i = 0; i < klass->field.count; i++) {
10978 klass->fields [i] = gklass->fields [i];
10979 klass->fields [i].parent = klass;
10980 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10984 /*We can only finish with this klass once it's parent has as well*/
10985 if (gklass->wastypebuilder)
10986 klass->wastypebuilder = TRUE;
10991 ensure_generic_class_runtime_vtable (MonoClass *klass)
10993 MonoClass *gklass = klass->generic_class->container_class;
10995 ensure_runtime_vtable (gklass);
10997 fix_partial_generic_class (klass);
11001 ensure_runtime_vtable (MonoClass *klass)
11003 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11006 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11009 ensure_runtime_vtable (klass->parent);
11012 num = tb->ctors? mono_array_length (tb->ctors): 0;
11013 num += tb->num_methods;
11014 klass->method.count = num;
11015 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11016 num = tb->ctors? mono_array_length (tb->ctors): 0;
11017 for (i = 0; i < num; ++i)
11018 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11019 num = tb->num_methods;
11021 for (i = 0; i < num; ++i)
11022 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11024 if (tb->interfaces) {
11025 klass->interface_count = mono_array_length (tb->interfaces);
11026 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11027 for (i = 0; i < klass->interface_count; ++i) {
11028 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11029 klass->interfaces [i] = mono_class_from_mono_type (iface);
11030 ensure_runtime_vtable (klass->interfaces [i]);
11032 klass->interfaces_inited = 1;
11034 } else if (klass->generic_class){
11035 ensure_generic_class_runtime_vtable (klass);
11038 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11040 for (i = 0; i < klass->method.count; ++i) {
11041 MonoMethod *im = klass->methods [i];
11042 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11043 im->slot = slot_num++;
11046 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11047 mono_class_setup_interface_offsets (klass);
11048 mono_class_setup_interface_id (klass);
11052 * The generic vtable is needed even if image->run is not set since some
11053 * runtime code like ves_icall_Type_GetMethodsByName depends on
11054 * method->slot being defined.
11058 * tb->methods could not be freed since it is used for determining
11059 * overrides during dynamic vtable construction.
11064 mono_reflection_method_get_handle (MonoObject *method)
11066 MonoClass *class = mono_object_class (method);
11067 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11068 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11069 return sr_method->method;
11071 if (is_sre_method_builder (class)) {
11072 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11073 return mb->mhandle;
11075 if (is_sre_method_on_tb_inst (class)) {
11076 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11077 MonoMethod *result;
11078 /*FIXME move this to a proper method and unify with resolve_object*/
11079 if (m->method_args) {
11080 result = mono_reflection_method_on_tb_inst_get_handle (m);
11082 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11083 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11084 MonoMethod *mono_method;
11086 if (is_sre_method_builder (mono_object_class (m->mb)))
11087 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11088 else if (is_sr_mono_method (mono_object_class (m->mb)))
11089 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11091 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)));
11093 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11098 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11103 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11105 MonoReflectionTypeBuilder *tb;
11107 MonoReflectionMethod *m;
11110 *num_overrides = 0;
11112 g_assert (image_is_dynamic (klass->image));
11114 if (!mono_class_get_ref_info (klass))
11117 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11119 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11123 for (i = 0; i < tb->num_methods; ++i) {
11124 MonoReflectionMethodBuilder *mb =
11125 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11126 if (mb->override_methods)
11127 onum += mono_array_length (mb->override_methods);
11132 *overrides = g_new0 (MonoMethod*, onum * 2);
11135 for (i = 0; i < tb->num_methods; ++i) {
11136 MonoReflectionMethodBuilder *mb =
11137 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11138 if (mb->override_methods) {
11139 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11140 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11142 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11143 (*overrides) [onum * 2 + 1] = mb->mhandle;
11145 g_assert (mb->mhandle);
11153 *num_overrides = onum;
11157 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11159 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11160 MonoReflectionFieldBuilder *fb;
11161 MonoClassField *field;
11162 MonoImage *image = klass->image;
11163 const char *p, *p2;
11165 guint32 len, idx, real_size = 0;
11167 klass->field.count = tb->num_fields;
11168 klass->field.first = 0;
11170 mono_error_init (error);
11172 if (tb->class_size) {
11173 if ((tb->packing_size & 0xffffff00) != 0) {
11174 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11175 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11178 klass->packing_size = tb->packing_size;
11179 real_size = klass->instance_size + tb->class_size;
11182 if (!klass->field.count) {
11183 klass->instance_size = MAX (klass->instance_size, real_size);
11187 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11188 mono_class_alloc_ext (klass);
11189 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11191 This is, guess what, a hack.
11192 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11193 On the static path no field class is resolved, only types are built. This is the right thing to do
11195 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11197 klass->size_inited = 1;
11199 for (i = 0; i < klass->field.count; ++i) {
11200 MonoArray *rva_data;
11201 fb = mono_array_get (tb->fields, gpointer, i);
11202 field = &klass->fields [i];
11203 field->name = mono_string_to_utf8_image (image, fb->name, error);
11204 if (!mono_error_ok (error))
11207 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11208 field->type->attrs = fb->attrs;
11210 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11213 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11214 char *base = mono_array_addr (rva_data, char, 0);
11215 size_t size = mono_array_length (rva_data);
11216 char *data = mono_image_alloc (klass->image, size);
11217 memcpy (data, base, size);
11218 klass->ext->field_def_values [i].data = data;
11220 if (fb->offset != -1)
11221 field->offset = fb->offset;
11222 field->parent = klass;
11223 fb->handle = field;
11224 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11226 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11227 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11229 if (fb->def_value) {
11230 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11231 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11232 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11233 /* Copy the data from the blob since it might get realloc-ed */
11234 p = assembly->blob.data + idx;
11235 len = mono_metadata_decode_blob_size (p, &p2);
11237 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11238 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11242 klass->instance_size = MAX (klass->instance_size, real_size);
11243 mono_class_layout_fields (klass);
11247 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11249 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11250 MonoReflectionPropertyBuilder *pb;
11251 MonoImage *image = klass->image;
11252 MonoProperty *properties;
11255 mono_error_init (error);
11258 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11260 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11261 klass->ext->property.first = 0;
11263 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11264 klass->ext->properties = properties;
11265 for (i = 0; i < klass->ext->property.count; ++i) {
11266 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11267 properties [i].parent = klass;
11268 properties [i].attrs = pb->attrs;
11269 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11270 if (!mono_error_ok (error))
11272 if (pb->get_method)
11273 properties [i].get = pb->get_method->mhandle;
11274 if (pb->set_method)
11275 properties [i].set = pb->set_method->mhandle;
11277 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11278 if (pb->def_value) {
11280 const char *p, *p2;
11281 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11282 if (!klass->ext->prop_def_values)
11283 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11284 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11285 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11286 /* Copy the data from the blob since it might get realloc-ed */
11287 p = assembly->blob.data + idx;
11288 len = mono_metadata_decode_blob_size (p, &p2);
11290 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11291 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11296 MonoReflectionEvent *
11297 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11299 MonoEvent *event = g_new0 (MonoEvent, 1);
11302 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11304 event->parent = klass;
11305 event->attrs = eb->attrs;
11306 event->name = mono_string_to_utf8 (eb->name);
11307 if (eb->add_method)
11308 event->add = eb->add_method->mhandle;
11309 if (eb->remove_method)
11310 event->remove = eb->remove_method->mhandle;
11311 if (eb->raise_method)
11312 event->raise = eb->raise_method->mhandle;
11314 #ifndef MONO_SMALL_CONFIG
11315 if (eb->other_methods) {
11317 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11318 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11319 MonoReflectionMethodBuilder *mb =
11320 mono_array_get (eb->other_methods,
11321 MonoReflectionMethodBuilder*, j);
11322 event->other [j] = mb->mhandle;
11327 return mono_event_get_object (mono_object_domain (tb), klass, event);
11331 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11333 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11334 MonoReflectionEventBuilder *eb;
11335 MonoImage *image = klass->image;
11339 mono_error_init (error);
11342 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11344 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11345 klass->ext->event.first = 0;
11347 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11348 klass->ext->events = events;
11349 for (i = 0; i < klass->ext->event.count; ++i) {
11350 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11351 events [i].parent = klass;
11352 events [i].attrs = eb->attrs;
11353 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11354 if (!mono_error_ok (error))
11356 if (eb->add_method)
11357 events [i].add = eb->add_method->mhandle;
11358 if (eb->remove_method)
11359 events [i].remove = eb->remove_method->mhandle;
11360 if (eb->raise_method)
11361 events [i].raise = eb->raise_method->mhandle;
11363 #ifndef MONO_SMALL_CONFIG
11364 if (eb->other_methods) {
11366 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11367 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11368 MonoReflectionMethodBuilder *mb =
11369 mono_array_get (eb->other_methods,
11370 MonoReflectionMethodBuilder*, j);
11371 events [i].other [j] = mb->mhandle;
11375 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11380 remove_instantiations_of_and_ensure_contents (gpointer key,
11382 gpointer user_data)
11384 MonoType *type = (MonoType*)key;
11385 MonoClass *klass = (MonoClass*)user_data;
11387 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11388 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11395 check_array_for_usertypes (MonoArray *arr)
11402 for (i = 0; i < mono_array_length (arr); ++i)
11403 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11406 MonoReflectionType*
11407 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11411 MonoDomain* domain;
11412 MonoReflectionType* res;
11415 domain = mono_object_domain (tb);
11416 klass = mono_class_from_mono_type (tb->type.type);
11419 * Check for user defined Type subclasses.
11421 RESOLVE_TYPE (tb->parent);
11422 check_array_for_usertypes (tb->interfaces);
11424 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11425 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11427 RESOLVE_TYPE (fb->type);
11428 check_array_for_usertypes (fb->modreq);
11429 check_array_for_usertypes (fb->modopt);
11430 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11431 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11436 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11437 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11439 RESOLVE_TYPE (mb->rtype);
11440 check_array_for_usertypes (mb->return_modreq);
11441 check_array_for_usertypes (mb->return_modopt);
11442 check_array_for_usertypes (mb->parameters);
11443 if (mb->param_modreq)
11444 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11445 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11446 if (mb->param_modopt)
11447 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11448 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11453 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11454 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11456 check_array_for_usertypes (mb->parameters);
11457 if (mb->param_modreq)
11458 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11459 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11460 if (mb->param_modopt)
11461 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11462 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11467 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11470 * we need to lock the domain because the lock will be taken inside
11471 * So, we need to keep the locking order correct.
11473 mono_loader_lock ();
11474 mono_domain_lock (domain);
11475 if (klass->wastypebuilder) {
11476 mono_domain_unlock (domain);
11477 mono_loader_unlock ();
11478 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11481 * Fields to set in klass:
11482 * the various flags: delegate/unicode/contextbound etc.
11484 klass->flags = tb->attrs;
11485 klass->has_cctor = 1;
11486 klass->has_finalize = 1;
11487 klass->has_finalize_inited = 1;
11489 mono_class_setup_parent (klass, klass->parent);
11490 /* fool mono_class_setup_supertypes */
11491 klass->supertypes = NULL;
11492 mono_class_setup_supertypes (klass);
11493 mono_class_setup_mono_type (klass);
11496 if (!((MonoDynamicImage*)klass->image)->run) {
11497 if (klass->generic_container) {
11498 /* FIXME: The code below can't handle generic classes */
11499 klass->wastypebuilder = TRUE;
11500 mono_loader_unlock ();
11501 mono_domain_unlock (domain);
11502 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11507 /* enums are done right away */
11508 if (!klass->enumtype)
11509 ensure_runtime_vtable (klass);
11511 if (tb->subtypes) {
11512 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11513 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11514 mono_class_alloc_ext (klass);
11515 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)));
11519 klass->nested_classes_inited = TRUE;
11521 /* fields and object layout */
11522 if (klass->parent) {
11523 if (!klass->parent->size_inited)
11524 mono_class_init (klass->parent);
11525 klass->instance_size = klass->parent->instance_size;
11526 klass->sizes.class_size = 0;
11527 klass->min_align = klass->parent->min_align;
11528 /* if the type has no fields we won't call the field_setup
11529 * routine which sets up klass->has_references.
11531 klass->has_references |= klass->parent->has_references;
11533 klass->instance_size = sizeof (MonoObject);
11534 klass->min_align = 1;
11537 /* FIXME: handle packing_size and instance_size */
11538 typebuilder_setup_fields (klass, &error);
11539 if (!mono_error_ok (&error))
11541 typebuilder_setup_properties (klass, &error);
11542 if (!mono_error_ok (&error))
11545 typebuilder_setup_events (klass, &error);
11546 if (!mono_error_ok (&error))
11549 klass->wastypebuilder = TRUE;
11552 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11553 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11554 * we want to return normal System.MonoType objects, so clear these out from the cache.
11556 * Together with this we must ensure the contents of all instances to match the created type.
11558 if (domain->type_hash && klass->generic_container)
11559 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11561 mono_domain_unlock (domain);
11562 mono_loader_unlock ();
11564 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11565 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11566 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11569 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11570 g_assert (res != (MonoReflectionType*)tb);
11575 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11576 klass->wastypebuilder = TRUE;
11577 mono_domain_unlock (domain);
11578 mono_loader_unlock ();
11579 mono_error_raise_exception (&error);
11584 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11586 MonoGenericParamFull *param;
11591 image = &gparam->tbuilder->module->dynamic_image->image;
11593 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11595 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11596 g_assert (mono_error_ok (&error));
11597 param->param.num = gparam->index;
11599 if (gparam->mbuilder) {
11600 if (!gparam->mbuilder->generic_container) {
11601 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11602 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11603 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11604 gparam->mbuilder->generic_container->is_method = TRUE;
11606 * Cannot set owner.method, since the MonoMethod is not created yet.
11607 * Set the image field instead, so type_in_image () works.
11609 gparam->mbuilder->generic_container->image = klass->image;
11611 param->param.owner = gparam->mbuilder->generic_container;
11612 } else if (gparam->tbuilder) {
11613 if (!gparam->tbuilder->generic_container) {
11614 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11615 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11616 gparam->tbuilder->generic_container->owner.klass = klass;
11618 param->param.owner = gparam->tbuilder->generic_container;
11621 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11623 gparam->type.type = &pklass->byval_arg;
11625 mono_class_set_ref_info (pklass, gparam);
11626 mono_image_append_class_to_reflection_info_set (pklass);
11630 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11632 MonoReflectionModuleBuilder *module = sig->module;
11633 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11634 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11639 check_array_for_usertypes (sig->arguments);
11641 sigbuffer_init (&buf, 32);
11643 sigbuffer_add_value (&buf, 0x07);
11644 sigbuffer_add_value (&buf, na);
11645 if (assembly != NULL){
11646 for (i = 0; i < na; ++i) {
11647 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11648 encode_reflection_type (assembly, type, &buf);
11652 buflen = buf.p - buf.buf;
11653 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11654 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11655 sigbuffer_free (&buf);
11661 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11663 MonoDynamicImage *assembly = sig->module->dynamic_image;
11664 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11669 check_array_for_usertypes (sig->arguments);
11671 sigbuffer_init (&buf, 32);
11673 sigbuffer_add_value (&buf, 0x06);
11674 for (i = 0; i < na; ++i) {
11675 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11676 encode_reflection_type (assembly, type, &buf);
11679 buflen = buf.p - buf.buf;
11680 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11681 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11682 sigbuffer_free (&buf);
11688 MonoMethod *handle;
11689 MonoDomain *domain;
11690 } DynamicMethodReleaseData;
11693 * The runtime automatically clean up those after finalization.
11695 static MonoReferenceQueue *dynamic_method_queue;
11698 free_dynamic_method (void *dynamic_method)
11700 DynamicMethodReleaseData *data = dynamic_method;
11702 mono_runtime_free_method (data->domain, data->handle);
11707 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11709 MonoReferenceQueue *queue;
11710 MonoMethod *handle;
11711 DynamicMethodReleaseData *release_data;
11712 ReflectionMethodBuilder rmb;
11713 MonoMethodSignature *sig;
11718 if (mono_runtime_is_shutting_down ())
11719 mono_raise_exception (mono_get_exception_invalid_operation (""));
11721 if (!(queue = dynamic_method_queue)) {
11722 mono_loader_lock ();
11723 if (!(queue = dynamic_method_queue))
11724 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11725 mono_loader_unlock ();
11728 sig = dynamic_method_to_signature (mb);
11730 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11733 * Resolve references.
11736 * Every second entry in the refs array is reserved for storing handle_class,
11737 * which is needed by the ldtoken implementation in the JIT.
11739 rmb.nrefs = mb->nrefs;
11740 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11741 for (i = 0; i < mb->nrefs; i += 2) {
11742 MonoClass *handle_class;
11744 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11746 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11747 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11749 * The referenced DynamicMethod should already be created by the managed
11750 * code, except in the case of circular references. In that case, we store
11751 * method in the refs array, and fix it up later when the referenced
11752 * DynamicMethod is created.
11754 if (method->mhandle) {
11755 ref = method->mhandle;
11757 /* FIXME: GC object stored in unmanaged memory */
11760 /* FIXME: GC object stored in unmanaged memory */
11761 method->referenced_by = g_slist_append (method->referenced_by, mb);
11763 handle_class = mono_defaults.methodhandle_class;
11765 MonoException *ex = NULL;
11766 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11768 ex = mono_get_exception_type_load (NULL, NULL);
11769 else if (mono_security_core_clr_enabled ())
11770 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11774 mono_raise_exception (ex);
11779 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11780 rmb.refs [i + 1] = handle_class;
11783 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11785 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11786 release_data = g_new (DynamicMethodReleaseData, 1);
11787 release_data->handle = handle;
11788 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11789 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11790 g_free (release_data);
11792 /* Fix up refs entries pointing at us */
11793 for (l = mb->referenced_by; l; l = l->next) {
11794 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11795 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11798 g_assert (method->mhandle);
11800 data = (gpointer*)wrapper->method_data;
11801 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11802 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11803 data [i + 1] = mb->mhandle;
11806 g_slist_free (mb->referenced_by);
11810 /* ilgen is no longer needed */
11814 #endif /* DISABLE_REFLECTION_EMIT */
11818 * mono_reflection_is_valid_dynamic_token:
11820 * Returns TRUE if token is valid.
11824 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11826 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11829 MonoMethodSignature *
11830 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
11832 MonoMethodSignature *sig;
11833 g_assert (image_is_dynamic (image));
11835 mono_error_init (error);
11837 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11841 return mono_method_signature_checked (method, error);
11844 #ifndef DISABLE_REFLECTION_EMIT
11847 * mono_reflection_lookup_dynamic_token:
11849 * Finish the Builder object pointed to by TOKEN and return the corresponding
11850 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11851 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11854 * LOCKING: Take the loader lock
11857 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11859 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11863 mono_loader_lock ();
11864 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11865 mono_loader_unlock ();
11868 g_error ("Could not find required dynamic token 0x%08x", token);
11874 handle_class = &klass;
11875 return resolve_object (image, obj, handle_class, context);
11879 * ensure_complete_type:
11881 * Ensure that KLASS is completed if it is a dynamic type, or references
11885 ensure_complete_type (MonoClass *klass)
11887 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11888 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11890 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11892 // Asserting here could break a lot of code
11893 //g_assert (klass->wastypebuilder);
11896 if (klass->generic_class) {
11897 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11900 for (i = 0; i < inst->type_argc; ++i) {
11901 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11907 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11909 gpointer result = NULL;
11911 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11912 result = mono_string_intern ((MonoString*)obj);
11913 *handle_class = mono_defaults.string_class;
11915 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11916 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11917 MonoClass *mc = mono_class_from_mono_type (type);
11918 if (!mono_class_init (mc))
11919 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11922 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11923 result = mono_class_from_mono_type (inflated);
11924 mono_metadata_free_type (inflated);
11926 result = mono_class_from_mono_type (type);
11928 *handle_class = mono_defaults.typehandle_class;
11930 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11931 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11932 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11933 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11934 result = ((MonoReflectionMethod*)obj)->method;
11937 result = mono_class_inflate_generic_method_checked (result, context, &error);
11938 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11940 *handle_class = mono_defaults.methodhandle_class;
11942 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11943 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11944 result = mb->mhandle;
11946 /* Type is not yet created */
11947 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11949 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11952 * Hopefully this has been filled in by calling CreateType() on the
11956 * TODO: This won't work if the application finishes another
11957 * TypeBuilder instance instead of this one.
11959 result = mb->mhandle;
11963 result = mono_class_inflate_generic_method_checked (result, context, &error);
11964 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11966 *handle_class = mono_defaults.methodhandle_class;
11967 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11968 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11970 result = cb->mhandle;
11972 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11974 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11975 result = cb->mhandle;
11979 result = mono_class_inflate_generic_method_checked (result, context, &error);
11980 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11982 *handle_class = mono_defaults.methodhandle_class;
11983 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11984 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11986 ensure_complete_type (field->parent);
11988 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11989 MonoClass *class = mono_class_from_mono_type (inflated);
11990 MonoClassField *inflated_field;
11991 gpointer iter = NULL;
11992 mono_metadata_free_type (inflated);
11993 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11994 if (!strcmp (field->name, inflated_field->name))
11997 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11998 result = inflated_field;
12002 *handle_class = mono_defaults.fieldhandle_class;
12004 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12005 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12006 result = fb->handle;
12009 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12011 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12012 result = fb->handle;
12015 if (fb->handle && fb->handle->parent->generic_container) {
12016 MonoClass *klass = fb->handle->parent;
12017 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12018 MonoClass *inflated = mono_class_from_mono_type (type);
12020 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12022 mono_metadata_free_type (type);
12024 *handle_class = mono_defaults.fieldhandle_class;
12025 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12026 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12027 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12030 klass = type->data.klass;
12031 if (klass->wastypebuilder) {
12032 /* Already created */
12036 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12037 result = type->data.klass;
12040 *handle_class = mono_defaults.typehandle_class;
12041 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12042 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12043 MonoMethodSignature *sig;
12046 if (helper->arguments)
12047 nargs = mono_array_length (helper->arguments);
12051 sig = mono_metadata_signature_alloc (image, nargs);
12052 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12053 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12055 if (helper->unmanaged_call_conv) { /* unmanaged */
12056 sig->call_convention = helper->unmanaged_call_conv - 1;
12057 sig->pinvoke = TRUE;
12058 } else if (helper->call_conv & 0x02) {
12059 sig->call_convention = MONO_CALL_VARARG;
12061 sig->call_convention = MONO_CALL_DEFAULT;
12064 sig->param_count = nargs;
12065 /* TODO: Copy type ? */
12066 sig->ret = helper->return_type->type;
12067 for (i = 0; i < nargs; ++i)
12068 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12071 *handle_class = NULL;
12072 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12073 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12074 /* Already created by the managed code */
12075 g_assert (method->mhandle);
12076 result = method->mhandle;
12077 *handle_class = mono_defaults.methodhandle_class;
12078 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12079 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12080 type = mono_class_inflate_generic_type (type, context);
12081 result = mono_class_from_mono_type (type);
12082 *handle_class = mono_defaults.typehandle_class;
12084 mono_metadata_free_type (type);
12085 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12086 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12087 type = mono_class_inflate_generic_type (type, context);
12088 result = mono_class_from_mono_type (type);
12089 *handle_class = mono_defaults.typehandle_class;
12091 mono_metadata_free_type (type);
12092 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12093 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12094 MonoClass *inflated;
12096 MonoClassField *field;
12098 if (is_sre_field_builder (mono_object_class (f->fb)))
12099 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12100 else if (is_sr_mono_field (mono_object_class (f->fb)))
12101 field = ((MonoReflectionField*)f->fb)->field;
12103 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)));
12105 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12106 inflated = mono_class_from_mono_type (type);
12108 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12109 ensure_complete_type (field->parent);
12111 mono_metadata_free_type (type);
12112 *handle_class = mono_defaults.fieldhandle_class;
12113 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12114 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12115 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12116 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12117 MonoMethod *method;
12119 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12120 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12121 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12122 method = ((MonoReflectionMethod *)c->cb)->method;
12124 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)));
12126 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12127 *handle_class = mono_defaults.methodhandle_class;
12128 mono_metadata_free_type (type);
12129 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12130 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12131 if (m->method_args) {
12132 result = mono_reflection_method_on_tb_inst_get_handle (m);
12135 result = mono_class_inflate_generic_method_checked (result, context, &error);
12136 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12139 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12140 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12141 MonoMethod *method;
12143 if (is_sre_method_builder (mono_object_class (m->mb)))
12144 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12145 else if (is_sr_mono_method (mono_object_class (m->mb)))
12146 method = ((MonoReflectionMethod *)m->mb)->method;
12148 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)));
12150 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12151 mono_metadata_free_type (type);
12153 *handle_class = mono_defaults.methodhandle_class;
12154 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12155 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12158 MonoMethod *method;
12162 mtype = mono_reflection_type_get_handle (m->parent);
12163 klass = mono_class_from_mono_type (mtype);
12165 /* Find the method */
12167 name = mono_string_to_utf8 (m->name);
12169 while ((method = mono_class_get_methods (klass, &iter))) {
12170 if (!strcmp (method->name, name))
12177 // FIXME: Check parameters/return value etc. match
12180 *handle_class = mono_defaults.methodhandle_class;
12181 } else if (is_sre_array (mono_object_get_class(obj)) ||
12182 is_sre_byref (mono_object_get_class(obj)) ||
12183 is_sre_pointer (mono_object_get_class(obj))) {
12184 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12185 MonoType *type = mono_reflection_type_get_handle (ref_type);
12188 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12189 result = mono_class_from_mono_type (inflated);
12190 mono_metadata_free_type (inflated);
12192 result = mono_class_from_mono_type (type);
12194 *handle_class = mono_defaults.typehandle_class;
12196 g_print ("%s\n", obj->vtable->klass->name);
12197 g_assert_not_reached ();
12202 #else /* DISABLE_REFLECTION_EMIT */
12205 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12207 g_assert_not_reached ();
12212 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12214 g_assert_not_reached ();
12218 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12220 g_assert_not_reached ();
12224 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12226 g_assert_not_reached ();
12230 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12232 g_assert_not_reached ();
12236 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12238 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12242 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12244 g_assert_not_reached ();
12248 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12250 g_assert_not_reached ();
12253 MonoReflectionModule *
12254 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12256 g_assert_not_reached ();
12261 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12263 g_assert_not_reached ();
12268 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12270 g_assert_not_reached ();
12275 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12276 gboolean create_open_instance, gboolean register_token)
12278 g_assert_not_reached ();
12283 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12288 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12290 g_assert_not_reached ();
12294 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12297 *num_overrides = 0;
12300 MonoReflectionEvent *
12301 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12303 g_assert_not_reached ();
12307 MonoReflectionType*
12308 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12310 g_assert_not_reached ();
12315 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12317 g_assert_not_reached ();
12321 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12323 g_assert_not_reached ();
12328 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12330 g_assert_not_reached ();
12335 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12340 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12346 mono_reflection_type_get_handle (MonoReflectionType* ref)
12354 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12356 g_assert_not_reached ();
12359 #endif /* DISABLE_REFLECTION_EMIT */
12361 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12362 const static guint32 declsec_flags_map[] = {
12363 0x00000000, /* empty */
12364 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12365 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12366 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12367 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12368 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12369 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12370 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12371 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12372 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12373 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12374 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12375 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12376 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12377 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12378 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12379 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12380 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12381 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12385 * Returns flags that includes all available security action associated to the handle.
12386 * @token: metadata token (either for a class or a method)
12387 * @image: image where resides the metadata.
12390 mono_declsec_get_flags (MonoImage *image, guint32 token)
12392 int index = mono_metadata_declsec_from_index (image, token);
12393 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12394 guint32 result = 0;
12398 /* HasSecurity can be present for other, not specially encoded, attributes,
12399 e.g. SuppressUnmanagedCodeSecurityAttribute */
12403 for (i = index; i < t->rows; i++) {
12404 guint32 cols [MONO_DECL_SECURITY_SIZE];
12406 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12407 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12410 action = cols [MONO_DECL_SECURITY_ACTION];
12411 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12412 result |= declsec_flags_map [action];
12414 g_assert_not_reached ();
12421 * Get the security actions (in the form of flags) associated with the specified method.
12423 * @method: The method for which we want the declarative security flags.
12424 * Return the declarative security flags for the method (only).
12426 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12427 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12430 mono_declsec_flags_from_method (MonoMethod *method)
12432 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12433 /* FIXME: No cache (for the moment) */
12434 guint32 idx = mono_method_get_index (method);
12435 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12436 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12437 return mono_declsec_get_flags (method->klass->image, idx);
12443 * Get the security actions (in the form of flags) associated with the specified class.
12445 * @klass: The class for which we want the declarative security flags.
12446 * Return the declarative security flags for the class.
12448 * Note: We cache the flags inside the MonoClass structure as this will get
12449 * called very often (at least for each method).
12452 mono_declsec_flags_from_class (MonoClass *klass)
12454 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12455 if (!klass->ext || !klass->ext->declsec_flags) {
12458 idx = mono_metadata_token_index (klass->type_token);
12459 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12460 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12461 mono_loader_lock ();
12462 mono_class_alloc_ext (klass);
12463 mono_loader_unlock ();
12464 /* we cache the flags on classes */
12465 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12467 return klass->ext->declsec_flags;
12473 * Get the security actions (in the form of flags) associated with the specified assembly.
12475 * @assembly: The assembly for which we want the declarative security flags.
12476 * Return the declarative security flags for the assembly.
12479 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12481 guint32 idx = 1; /* there is only one assembly */
12482 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12483 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12484 return mono_declsec_get_flags (assembly->image, idx);
12489 * Fill actions for the specific index (which may either be an encoded class token or
12490 * an encoded method token) from the metadata image.
12491 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12494 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12495 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12497 MonoBoolean result = FALSE;
12499 guint32 cols [MONO_DECL_SECURITY_SIZE];
12500 int index = mono_metadata_declsec_from_index (image, token);
12503 t = &image->tables [MONO_TABLE_DECLSECURITY];
12504 for (i = index; i < t->rows; i++) {
12505 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12507 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12510 /* if present only replace (class) permissions with method permissions */
12511 /* if empty accept either class or method permissions */
12512 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12513 if (!actions->demand.blob) {
12514 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12515 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12516 actions->demand.blob = (char*) (blob + 2);
12517 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12520 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12521 if (!actions->noncasdemand.blob) {
12522 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12523 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12524 actions->noncasdemand.blob = (char*) (blob + 2);
12525 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12528 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12529 if (!actions->demandchoice.blob) {
12530 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12531 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12532 actions->demandchoice.blob = (char*) (blob + 2);
12533 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12543 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12544 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12546 guint32 idx = mono_metadata_token_index (klass->type_token);
12547 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12548 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12549 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12553 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12554 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12556 guint32 idx = mono_method_get_index (method);
12557 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12558 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12559 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12563 * Collect all actions (that requires to generate code in mini) assigned for
12564 * the specified method.
12565 * Note: Don't use the content of actions if the function return FALSE.
12568 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12570 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12571 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12572 MonoBoolean result = FALSE;
12575 /* quick exit if no declarative security is present in the metadata */
12576 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12579 /* we want the original as the wrapper is "free" of the security informations */
12580 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12581 method = mono_marshal_method_from_wrapper (method);
12586 /* First we look for method-level attributes */
12587 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12588 mono_class_init (method->klass);
12589 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12591 result = mono_declsec_get_method_demands_params (method, demands,
12592 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12595 /* Here we use (or create) the class declarative cache to look for demands */
12596 flags = mono_declsec_flags_from_class (method->klass);
12597 if (flags & mask) {
12599 mono_class_init (method->klass);
12600 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12602 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12603 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12606 /* The boolean return value is used as a shortcut in case nothing needs to
12607 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12613 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12615 * Note: Don't use the content of actions if the function return FALSE.
12618 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12620 MonoBoolean result = FALSE;
12623 /* quick exit if no declarative security is present in the metadata */
12624 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12627 /* we want the original as the wrapper is "free" of the security informations */
12628 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12629 method = mono_marshal_method_from_wrapper (method);
12634 /* results are independant - zeroize both */
12635 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12636 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12638 /* First we look for method-level attributes */
12639 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12640 mono_class_init (method->klass);
12642 result = mono_declsec_get_method_demands_params (method, cmethod,
12643 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12646 /* Here we use (or create) the class declarative cache to look for demands */
12647 flags = mono_declsec_flags_from_class (method->klass);
12648 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12649 mono_class_init (method->klass);
12651 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12652 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12659 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12661 * @klass The inherited class - this is the class that provides the security check (attributes)
12663 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12665 * Note: Don't use the content of actions if the function return FALSE.
12668 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12670 MonoBoolean result = FALSE;
12673 /* quick exit if no declarative security is present in the metadata */
12674 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12677 /* Here we use (or create) the class declarative cache to look for demands */
12678 flags = mono_declsec_flags_from_class (klass);
12679 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12680 mono_class_init (klass);
12681 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12683 result |= mono_declsec_get_class_demands_params (klass, demands,
12684 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12691 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12693 * Note: Don't use the content of actions if the function return FALSE.
12696 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12698 /* quick exit if no declarative security is present in the metadata */
12699 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12702 /* we want the original as the wrapper is "free" of the security informations */
12703 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12704 method = mono_marshal_method_from_wrapper (method);
12709 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12710 mono_class_init (method->klass);
12711 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12713 return mono_declsec_get_method_demands_params (method, demands,
12714 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12721 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12723 guint32 cols [MONO_DECL_SECURITY_SIZE];
12727 int index = mono_metadata_declsec_from_index (image, token);
12731 t = &image->tables [MONO_TABLE_DECLSECURITY];
12732 for (i = index; i < t->rows; i++) {
12733 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12735 /* shortcut - index are ordered */
12736 if (token != cols [MONO_DECL_SECURITY_PARENT])
12739 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12740 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12741 entry->blob = (char*) (metadata + 2);
12742 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12751 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12753 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12754 guint32 idx = mono_method_get_index (method);
12755 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12756 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12757 return get_declsec_action (method->klass->image, idx, action, entry);
12763 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12766 guint32 flags = mono_declsec_flags_from_class (klass);
12767 if (declsec_flags_map [action] & flags) {
12768 guint32 idx = mono_metadata_token_index (klass->type_token);
12769 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12770 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12771 return get_declsec_action (klass->image, idx, action, entry);
12777 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12779 guint32 idx = 1; /* there is only one assembly */
12780 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12781 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12783 return get_declsec_action (assembly->image, idx, action, entry);
12787 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12789 MonoObject *res, *exc;
12791 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12792 static MonoMethod *method = NULL;
12794 if (!System_Reflection_Emit_TypeBuilder) {
12795 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12796 g_assert (System_Reflection_Emit_TypeBuilder);
12798 if (method == NULL) {
12799 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12804 * The result of mono_type_get_object () might be a System.MonoType but we
12805 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12807 g_assert (mono_class_get_ref_info (klass));
12808 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12810 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12812 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12816 return *(MonoBoolean*)mono_object_unbox (res);
12820 * mono_reflection_type_get_type:
12821 * @reftype: the System.Type object
12823 * Returns the MonoType* associated with the C# System.Type object @reftype.
12826 mono_reflection_type_get_type (MonoReflectionType *reftype)
12828 g_assert (reftype);
12830 return mono_reflection_type_get_handle (reftype);
12834 * mono_reflection_assembly_get_assembly:
12835 * @refassembly: the System.Reflection.Assembly object
12837 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
12840 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
12842 g_assert (refassembly);
12844 return refassembly->assembly;