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 (ta->dynamic || (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) {
1705 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1707 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1709 token = type->modifiers [i].token;
1712 if (type->modifiers [i].required)
1713 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1715 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1717 sigbuffer_add_value (&buf, token);
1720 encode_type (assembly, type, &buf);
1721 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1722 sigbuffer_free (&buf);
1728 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1732 guint32 typespec = 0;
1736 init_type_builder_generics (fb->type);
1738 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1739 class = mono_class_from_mono_type (type);
1741 sigbuffer_init (&buf, 32);
1743 sigbuffer_add_value (&buf, 0x06);
1744 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1745 /* encode custom attributes before the type */
1747 if (class->generic_container)
1748 typespec = create_typespec (assembly, type);
1751 MonoGenericClass *gclass;
1752 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1753 encode_generic_class (assembly, gclass, &buf);
1755 encode_type (assembly, type, &buf);
1757 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1758 sigbuffer_free (&buf);
1763 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1764 char blob_size [64];
1765 char *b = blob_size;
1768 guint32 idx = 0, len = 0, dummy = 0;
1770 p = buf = g_malloc (64);
1772 *ret_type = MONO_TYPE_CLASS;
1774 box_val = (char*)&dummy;
1776 box_val = ((char*)val) + sizeof (MonoObject);
1777 *ret_type = val->vtable->klass->byval_arg.type;
1780 switch (*ret_type) {
1781 case MONO_TYPE_BOOLEAN:
1786 case MONO_TYPE_CHAR:
1803 case MONO_TYPE_VALUETYPE: {
1804 MonoClass *klass = val->vtable->klass;
1806 if (klass->enumtype) {
1807 *ret_type = mono_class_enum_basetype (klass)->type;
1809 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1812 g_error ("we can't encode valuetypes, we should have never reached this line");
1815 case MONO_TYPE_CLASS:
1817 case MONO_TYPE_STRING: {
1818 MonoString *str = (MonoString*)val;
1819 /* there is no signature */
1820 len = str->length * 2;
1821 mono_metadata_encode_value (len, b, &b);
1822 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1824 char *swapped = g_malloc (2 * mono_string_length (str));
1825 const char *p = (const char*)mono_string_chars (str);
1827 swap_with_size (swapped, p, 2, mono_string_length (str));
1828 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1832 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1838 case MONO_TYPE_GENERICINST:
1839 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1842 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1845 /* there is no signature */
1846 mono_metadata_encode_value (len, b, &b);
1847 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1848 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1849 swap_with_size (blob_size, box_val, len, 1);
1850 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1852 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1860 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1865 sigbuffer_init (&buf, 32);
1867 sigbuffer_add_value (&buf, minfo->type);
1869 switch (minfo->type) {
1870 case MONO_NATIVE_BYVALTSTR:
1871 case MONO_NATIVE_BYVALARRAY:
1872 sigbuffer_add_value (&buf, minfo->count);
1874 case MONO_NATIVE_LPARRAY:
1875 if (minfo->eltype || minfo->has_size) {
1876 sigbuffer_add_value (&buf, minfo->eltype);
1877 if (minfo->has_size) {
1878 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1879 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1881 /* LAMESPEC: ElemMult is undocumented */
1882 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1886 case MONO_NATIVE_SAFEARRAY:
1888 sigbuffer_add_value (&buf, minfo->eltype);
1890 case MONO_NATIVE_CUSTOM:
1892 str = mono_string_to_utf8 (minfo->guid);
1894 sigbuffer_add_value (&buf, len);
1895 sigbuffer_add_mem (&buf, str, len);
1898 sigbuffer_add_value (&buf, 0);
1900 /* native type name */
1901 sigbuffer_add_value (&buf, 0);
1902 /* custom marshaler type name */
1903 if (minfo->marshaltype || minfo->marshaltyperef) {
1904 if (minfo->marshaltyperef)
1905 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1907 str = mono_string_to_utf8 (minfo->marshaltype);
1909 sigbuffer_add_value (&buf, len);
1910 sigbuffer_add_mem (&buf, str, len);
1913 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1914 sigbuffer_add_value (&buf, 0);
1916 if (minfo->mcookie) {
1917 str = mono_string_to_utf8 (minfo->mcookie);
1919 sigbuffer_add_value (&buf, len);
1920 sigbuffer_add_mem (&buf, str, len);
1923 sigbuffer_add_value (&buf, 0);
1929 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1930 sigbuffer_free (&buf);
1935 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1937 MonoDynamicTable *table;
1940 /* maybe this fixup should be done in the C# code */
1941 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1942 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1943 table = &assembly->tables [MONO_TABLE_FIELD];
1944 fb->table_idx = table->next_idx ++;
1945 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1946 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1947 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1948 values [MONO_FIELD_FLAGS] = fb->attrs;
1949 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1951 if (fb->offset != -1) {
1952 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1954 alloc_table (table, table->rows);
1955 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1956 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1957 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1959 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1960 guint32 field_type = 0;
1961 table = &assembly->tables [MONO_TABLE_CONSTANT];
1963 alloc_table (table, table->rows);
1964 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1965 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1966 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1967 values [MONO_CONSTANT_TYPE] = field_type;
1968 values [MONO_CONSTANT_PADDING] = 0;
1970 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1972 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1974 alloc_table (table, table->rows);
1975 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1976 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1978 * We store it in the code section because it's simpler for now.
1981 if (mono_array_length (fb->rva_data) >= 10)
1982 stream_data_align (&assembly->code);
1983 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1985 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1986 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1988 if (fb->marshal_info) {
1989 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1991 alloc_table (table, table->rows);
1992 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1993 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1994 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1999 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2002 guint32 nparams = 0;
2003 MonoReflectionMethodBuilder *mb = fb->get_method;
2004 MonoReflectionMethodBuilder *smb = fb->set_method;
2007 if (mb && mb->parameters)
2008 nparams = mono_array_length (mb->parameters);
2009 if (!mb && smb && smb->parameters)
2010 nparams = mono_array_length (smb->parameters) - 1;
2011 sigbuffer_init (&buf, 32);
2012 if (fb->call_conv & 0x20)
2013 sigbuffer_add_byte (&buf, 0x28);
2015 sigbuffer_add_byte (&buf, 0x08);
2016 sigbuffer_add_value (&buf, nparams);
2018 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2019 for (i = 0; i < nparams; ++i) {
2020 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2021 encode_reflection_type (assembly, pt, &buf);
2023 } else if (smb && smb->parameters) {
2024 /* the property type is the last param */
2025 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2026 for (i = 0; i < nparams; ++i) {
2027 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2028 encode_reflection_type (assembly, pt, &buf);
2031 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2034 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2035 sigbuffer_free (&buf);
2040 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2042 MonoDynamicTable *table;
2044 guint num_methods = 0;
2048 * we need to set things in the following tables:
2049 * PROPERTYMAP (info already filled in _get_type_info ())
2050 * PROPERTY (rows already preallocated in _get_type_info ())
2051 * METHOD (method info already done with the generic method code)
2055 table = &assembly->tables [MONO_TABLE_PROPERTY];
2056 pb->table_idx = table->next_idx ++;
2057 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2058 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2059 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2060 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2062 /* FIXME: we still don't handle 'other' methods */
2063 if (pb->get_method) num_methods ++;
2064 if (pb->set_method) num_methods ++;
2066 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2067 table->rows += num_methods;
2068 alloc_table (table, table->rows);
2070 if (pb->get_method) {
2071 semaidx = table->next_idx ++;
2072 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2073 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2074 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2075 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2077 if (pb->set_method) {
2078 semaidx = table->next_idx ++;
2079 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2080 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2081 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2082 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2084 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2085 guint32 field_type = 0;
2086 table = &assembly->tables [MONO_TABLE_CONSTANT];
2088 alloc_table (table, table->rows);
2089 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2090 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2091 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2092 values [MONO_CONSTANT_TYPE] = field_type;
2093 values [MONO_CONSTANT_PADDING] = 0;
2098 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2100 MonoDynamicTable *table;
2102 guint num_methods = 0;
2106 * we need to set things in the following tables:
2107 * EVENTMAP (info already filled in _get_type_info ())
2108 * EVENT (rows already preallocated in _get_type_info ())
2109 * METHOD (method info already done with the generic method code)
2112 table = &assembly->tables [MONO_TABLE_EVENT];
2113 eb->table_idx = table->next_idx ++;
2114 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2115 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2116 values [MONO_EVENT_FLAGS] = eb->attrs;
2117 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2120 * FIXME: we still don't handle 'other' methods
2122 if (eb->add_method) num_methods ++;
2123 if (eb->remove_method) num_methods ++;
2124 if (eb->raise_method) num_methods ++;
2126 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2127 table->rows += num_methods;
2128 alloc_table (table, table->rows);
2130 if (eb->add_method) {
2131 semaidx = table->next_idx ++;
2132 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2133 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2134 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2135 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2137 if (eb->remove_method) {
2138 semaidx = table->next_idx ++;
2139 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2140 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2141 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2142 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2144 if (eb->raise_method) {
2145 semaidx = table->next_idx ++;
2146 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2147 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2148 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2149 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2154 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2156 MonoDynamicTable *table;
2157 guint32 num_constraints, i;
2161 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2162 num_constraints = gparam->iface_constraints ?
2163 mono_array_length (gparam->iface_constraints) : 0;
2164 table->rows += num_constraints;
2165 if (gparam->base_type)
2167 alloc_table (table, table->rows);
2169 if (gparam->base_type) {
2170 table_idx = table->next_idx ++;
2171 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2173 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2174 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2175 assembly, mono_reflection_type_get_handle (gparam->base_type));
2178 for (i = 0; i < num_constraints; i++) {
2179 MonoReflectionType *constraint = mono_array_get (
2180 gparam->iface_constraints, gpointer, i);
2182 table_idx = table->next_idx ++;
2183 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2185 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2186 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2187 assembly, mono_reflection_type_get_handle (constraint));
2192 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2194 GenericParamTableEntry *entry;
2197 * The GenericParam table must be sorted according to the `owner' field.
2198 * We need to do this sorting prior to writing the GenericParamConstraint
2199 * table, since we have to use the final GenericParam table indices there
2200 * and they must also be sorted.
2203 entry = g_new0 (GenericParamTableEntry, 1);
2204 entry->owner = owner;
2205 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2206 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2207 entry->gparam = gparam;
2209 g_ptr_array_add (assembly->gen_params, entry);
2213 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2215 MonoDynamicTable *table;
2216 MonoGenericParam *param;
2220 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2221 table_idx = table->next_idx ++;
2222 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2224 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2226 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2227 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2228 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2229 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2231 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2233 encode_constraints (entry->gparam, table_idx, assembly);
2237 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2239 MonoDynamicTable *table;
2242 guint32 cols [MONO_ASSEMBLY_SIZE];
2246 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2249 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2250 table = &assembly->tables [MONO_TABLE_MODULEREF];
2251 token = table->next_idx ++;
2253 alloc_table (table, table->rows);
2254 values = table->values + token * MONO_MODULEREF_SIZE;
2255 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2257 token <<= MONO_RESOLTION_SCOPE_BITS;
2258 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2259 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2264 if (image->assembly->dynamic)
2266 memset (cols, 0, sizeof (cols));
2268 /* image->assembly->image is the manifest module */
2269 image = image->assembly->image;
2270 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2273 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2274 token = table->next_idx ++;
2276 alloc_table (table, table->rows);
2277 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2278 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2279 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2280 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2281 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2282 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2283 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2284 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2285 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2287 if (strcmp ("", image->assembly->aname.culture)) {
2288 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2289 image->assembly->aname.culture);
2292 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2293 guchar pubtoken [9];
2295 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2296 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2298 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2300 token <<= MONO_RESOLTION_SCOPE_BITS;
2301 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2302 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2307 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2309 MonoDynamicTable *table;
2314 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2317 sigbuffer_init (&buf, 32);
2318 switch (type->type) {
2319 case MONO_TYPE_FNPTR:
2321 case MONO_TYPE_SZARRAY:
2322 case MONO_TYPE_ARRAY:
2324 case MONO_TYPE_MVAR:
2325 case MONO_TYPE_GENERICINST:
2326 encode_type (assembly, type, &buf);
2328 case MONO_TYPE_CLASS:
2329 case MONO_TYPE_VALUETYPE: {
2330 MonoClass *k = mono_class_from_mono_type (type);
2331 if (!k || !k->generic_container) {
2332 sigbuffer_free (&buf);
2335 encode_type (assembly, type, &buf);
2339 sigbuffer_free (&buf);
2343 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2344 if (assembly->save) {
2345 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2346 alloc_table (table, table->rows + 1);
2347 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2348 values [MONO_TYPESPEC_SIGNATURE] = token;
2350 sigbuffer_free (&buf);
2352 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2353 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2359 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2361 MonoDynamicTable *table;
2363 guint32 token, scope, enclosing;
2366 /* if the type requires a typespec, we must try that first*/
2367 if (try_typespec && (token = create_typespec (assembly, type)))
2369 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2372 klass = mono_class_from_mono_type (type);
2374 klass = mono_class_from_mono_type (type);
2377 * If it's in the same module and not a generic type parameter:
2379 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2380 (type->type != MONO_TYPE_MVAR)) {
2381 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2382 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2383 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2387 if (klass->nested_in) {
2388 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2389 /* get the typeref idx of the enclosing type */
2390 enclosing >>= MONO_TYPEDEFORREF_BITS;
2391 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2393 scope = resolution_scope_from_image (assembly, klass->image);
2395 table = &assembly->tables [MONO_TABLE_TYPEREF];
2396 if (assembly->save) {
2397 alloc_table (table, table->rows + 1);
2398 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2399 values [MONO_TYPEREF_SCOPE] = scope;
2400 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2401 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2403 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2404 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2406 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2411 * Despite the name, we handle also TypeSpec (with the above helper).
2414 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2416 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2419 #ifndef DISABLE_REFLECTION_EMIT
2421 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2423 MonoDynamicTable *table;
2425 guint32 token, pclass;
2427 switch (parent & MONO_TYPEDEFORREF_MASK) {
2428 case MONO_TYPEDEFORREF_TYPEREF:
2429 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2431 case MONO_TYPEDEFORREF_TYPESPEC:
2432 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2434 case MONO_TYPEDEFORREF_TYPEDEF:
2435 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2438 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2441 /* extract the index */
2442 parent >>= MONO_TYPEDEFORREF_BITS;
2444 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2446 if (assembly->save) {
2447 alloc_table (table, table->rows + 1);
2448 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2449 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2450 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2451 values [MONO_MEMBERREF_SIGNATURE] = sig;
2454 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2461 * Insert a memberef row into the metadata: the token that point to the memberref
2462 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2463 * mono_image_get_fieldref_token()).
2464 * The sig param is an index to an already built signature.
2467 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2469 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2470 return mono_image_add_memberef_row (assembly, parent, name, sig);
2475 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2478 MonoMethodSignature *sig;
2480 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2482 if (create_typespec) {
2483 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2488 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2489 if (token && !create_typespec)
2492 g_assert (!method->is_inflated);
2495 * A methodref signature can't contain an unmanaged calling convention.
2497 sig = mono_metadata_signature_dup (mono_method_signature (method));
2498 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2499 sig->call_convention = MONO_CALL_DEFAULT;
2500 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2501 method->name, method_encode_signature (assembly, sig));
2503 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2506 if (create_typespec) {
2507 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2508 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2509 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2511 if (assembly->save) {
2514 alloc_table (table, table->rows + 1);
2515 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2516 values [MONO_METHODSPEC_METHOD] = token;
2517 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2520 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2522 /*methodspec and memberef tokens are diferent, */
2523 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2530 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2532 guint32 token, parent, sig;
2533 ReflectionMethodBuilder rmb;
2535 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2537 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2541 name = mono_string_to_utf8 (method->name);
2542 reflection_methodbuilder_from_method_builder (&rmb, method);
2545 * A methodref signature can't contain an unmanaged calling convention.
2546 * Since some flags are encoded as part of call_conv, we need to check against it.
2548 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2549 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2551 sig = method_builder_encode_signature (assembly, &rmb);
2553 if (tb->generic_params)
2554 parent = create_generic_typespec (assembly, tb);
2556 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2558 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2561 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2566 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2567 const gchar *name, guint32 sig)
2569 MonoDynamicTable *table;
2573 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2575 if (assembly->save) {
2576 alloc_table (table, table->rows + 1);
2577 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2578 values [MONO_MEMBERREF_CLASS] = original;
2579 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2580 values [MONO_MEMBERREF_SIGNATURE] = sig;
2583 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2590 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2594 guint32 nparams = mono_array_length (mb->generic_params);
2597 if (!assembly->save)
2600 sigbuffer_init (&buf, 32);
2602 sigbuffer_add_value (&buf, 0xa);
2603 sigbuffer_add_value (&buf, nparams);
2605 for (i = 0; i < nparams; i++) {
2606 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2607 sigbuffer_add_value (&buf, i);
2610 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2611 sigbuffer_free (&buf);
2616 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2618 MonoDynamicTable *table;
2620 guint32 token, mtoken = 0;
2622 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2626 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2628 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2629 switch (mono_metadata_token_table (mtoken)) {
2630 case MONO_TABLE_MEMBERREF:
2631 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2633 case MONO_TABLE_METHOD:
2634 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2637 g_assert_not_reached ();
2640 if (assembly->save) {
2641 alloc_table (table, table->rows + 1);
2642 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2643 values [MONO_METHODSPEC_METHOD] = mtoken;
2644 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2647 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2650 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2655 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2659 if (mb->generic_params && create_methodspec)
2660 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2662 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2666 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2667 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2672 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2674 guint32 token, parent, sig;
2675 ReflectionMethodBuilder rmb;
2677 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2679 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2683 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2685 if (tb->generic_params)
2686 parent = create_generic_typespec (assembly, tb);
2688 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2690 name = mono_string_to_utf8 (rmb.name);
2691 sig = method_builder_encode_signature (assembly, &rmb);
2693 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2696 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2702 is_field_on_inst (MonoClassField *field)
2704 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2708 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2711 get_field_on_inst_generic_type (MonoClassField *field)
2713 MonoClass *class, *gtd;
2714 MonoDynamicGenericClass *dgclass;
2717 g_assert (is_field_on_inst (field));
2719 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2721 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2722 field_index = field - dgclass->fields;
2723 return dgclass->field_generic_types [field_index];
2726 class = field->parent;
2727 gtd = class->generic_class->container_class;
2729 if (field >= class->fields && field - class->fields < class->field.count) {
2730 field_index = field - class->fields;
2731 return gtd->fields [field_index].type;
2734 g_assert_not_reached ();
2738 #ifndef DISABLE_REFLECTION_EMIT
2740 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2746 g_assert (field->parent);
2748 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2752 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2753 int index = field - field->parent->fields;
2754 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2756 if (is_field_on_inst (field))
2757 type = get_field_on_inst_generic_type (field);
2759 type = mono_field_get_type (field);
2761 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2762 mono_field_get_name (field),
2763 fieldref_encode_signature (assembly, field->parent->image, type));
2764 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2769 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2773 MonoGenericClass *gclass;
2774 MonoDynamicGenericClass *dgclass;
2778 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2781 if (is_sre_field_builder (mono_object_class (f->fb))) {
2782 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2783 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2784 klass = mono_class_from_mono_type (type);
2785 gclass = type->data.generic_class;
2786 g_assert (gclass->is_dynamic);
2787 dgclass = (MonoDynamicGenericClass *) gclass;
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 MonoDynamicGenericClass *dgclass;
2828 ReflectionMethodBuilder rmb;
2831 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2832 klass = mono_class_from_mono_type (type);
2834 gclass = type->data.generic_class;
2835 g_assert (gclass->is_dynamic);
2836 dgclass = (MonoDynamicGenericClass *) gclass;
2838 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2840 name = mono_string_to_utf8 (rmb.name);
2842 sig = method_builder_encode_signature (assembly, &rmb);
2844 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2846 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2847 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2849 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2850 klass = mono_class_from_mono_type (type);
2852 sig = method_encode_signature (assembly, mono_method_signature (mm));
2853 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2855 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2856 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2860 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2865 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2868 MonoGenericContext tmp_context;
2869 MonoType **type_argv;
2870 MonoGenericInst *ginst;
2871 MonoMethod *method, *inflated;
2874 init_type_builder_generics ((MonoObject*)m->inst);
2876 method = inflate_method (m->inst, (MonoObject*)m->mb);
2878 klass = method->klass;
2880 if (m->method_args == NULL)
2883 if (method->is_inflated)
2884 method = ((MonoMethodInflated *) method)->declaring;
2886 count = mono_array_length (m->method_args);
2888 type_argv = g_new0 (MonoType *, count);
2889 for (i = 0; i < count; i++) {
2890 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2891 type_argv [i] = mono_reflection_type_get_handle (garg);
2893 ginst = mono_metadata_get_generic_inst (count, type_argv);
2896 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2897 tmp_context.method_inst = ginst;
2899 inflated = mono_class_inflate_generic_method (method, &tmp_context);
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;
3195 MonoType *custom = NULL, *type;
3197 guint32 token, pclass, parent, sig;
3200 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3204 klass = 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)
3250 if (!assembly->save)
3253 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3254 g_assert (helper->type == 2);
3256 if (helper->arguments)
3257 nargs = mono_array_length (helper->arguments);
3261 size = 10 + (nargs * 10);
3263 sigbuffer_init (&buf, 32);
3265 /* Encode calling convention */
3266 /* Change Any to Standard */
3267 if ((helper->call_conv & 0x03) == 0x03)
3268 helper->call_conv = 0x01;
3269 /* explicit_this implies has_this */
3270 if (helper->call_conv & 0x40)
3271 helper->call_conv &= 0x20;
3273 if (helper->call_conv == 0) { /* Unmanaged */
3274 idx = helper->unmanaged_call_conv - 1;
3277 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3278 if (helper->call_conv & 0x02) /* varargs */
3282 sigbuffer_add_byte (&buf, idx);
3283 sigbuffer_add_value (&buf, nargs);
3284 encode_reflection_type (assembly, helper->return_type, &buf);
3285 for (i = 0; i < nargs; ++i) {
3286 MonoArray *modreqs = NULL;
3287 MonoArray *modopts = NULL;
3288 MonoReflectionType *pt;
3290 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3291 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3292 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3293 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3295 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3296 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3297 encode_reflection_type (assembly, pt, &buf);
3299 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3300 sigbuffer_free (&buf);
3306 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3309 MonoDynamicTable *table;
3312 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3313 idx = table->next_idx ++;
3315 alloc_table (table, table->rows);
3316 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3318 values [MONO_STAND_ALONE_SIGNATURE] =
3319 mono_reflection_encode_sighelper (assembly, helper);
3325 reflection_cc_to_file (int call_conv) {
3326 switch (call_conv & 0x3) {
3328 case 1: return MONO_CALL_DEFAULT;
3329 case 2: return MONO_CALL_VARARG;
3331 g_assert_not_reached ();
3335 #endif /* !DISABLE_REFLECTION_EMIT */
3339 MonoMethodSignature *sig;
3344 #ifndef DISABLE_REFLECTION_EMIT
3346 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3351 MonoMethodSignature *sig;
3355 name = mono_string_to_utf8 (m->name);
3356 nparams = mono_array_length (m->parameters);
3357 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3359 sig->sentinelpos = -1;
3360 sig->call_convention = reflection_cc_to_file (m->call_conv);
3361 sig->param_count = nparams;
3362 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3363 mtype = mono_reflection_type_get_handle (m->parent);
3364 for (i = 0; i < nparams; ++i)
3365 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3367 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3369 if (strcmp (name, am->name) == 0 &&
3370 mono_metadata_type_equal (am->parent, mtype) &&
3371 mono_metadata_signature_equal (am->sig, sig)) {
3374 m->table_idx = am->token & 0xffffff;
3378 am = g_new0 (ArrayMethod, 1);
3382 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3383 method_encode_signature (assembly, sig));
3384 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3385 m->table_idx = am->token & 0xffffff;
3390 * Insert into the metadata tables all the info about the TypeBuilder tb.
3391 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3394 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3396 MonoDynamicTable *table;
3398 int i, is_object = 0, is_system = 0;
3401 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3402 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3403 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3404 n = mono_string_to_utf8 (tb->name);
3405 if (strcmp (n, "Object") == 0)
3407 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3409 n = mono_string_to_utf8 (tb->nspace);
3410 if (strcmp (n, "System") == 0)
3412 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3414 if (tb->parent && !(is_system && is_object) &&
3415 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3416 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3418 values [MONO_TYPEDEF_EXTENDS] = 0;
3420 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3421 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3424 * if we have explicitlayout or sequentiallayouts, output data in the
3425 * ClassLayout table.
3427 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3428 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3429 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3431 alloc_table (table, table->rows);
3432 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3433 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3434 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3435 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3438 /* handle interfaces */
3439 if (tb->interfaces) {
3440 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3442 table->rows += mono_array_length (tb->interfaces);
3443 alloc_table (table, table->rows);
3444 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3445 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3446 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3447 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3448 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3449 values += MONO_INTERFACEIMPL_SIZE;
3455 table = &assembly->tables [MONO_TABLE_FIELD];
3456 table->rows += tb->num_fields;
3457 alloc_table (table, table->rows);
3458 for (i = 0; i < tb->num_fields; ++i)
3459 mono_image_get_field_info (
3460 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3463 /* handle constructors */
3465 table = &assembly->tables [MONO_TABLE_METHOD];
3466 table->rows += mono_array_length (tb->ctors);
3467 alloc_table (table, table->rows);
3468 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3469 mono_image_get_ctor_info (domain,
3470 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3473 /* handle methods */
3475 table = &assembly->tables [MONO_TABLE_METHOD];
3476 table->rows += tb->num_methods;
3477 alloc_table (table, table->rows);
3478 for (i = 0; i < tb->num_methods; ++i)
3479 mono_image_get_method_info (
3480 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3483 /* Do the same with properties etc.. */
3484 if (tb->events && mono_array_length (tb->events)) {
3485 table = &assembly->tables [MONO_TABLE_EVENT];
3486 table->rows += mono_array_length (tb->events);
3487 alloc_table (table, table->rows);
3488 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3490 alloc_table (table, table->rows);
3491 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3492 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3493 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3494 for (i = 0; i < mono_array_length (tb->events); ++i)
3495 mono_image_get_event_info (
3496 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3498 if (tb->properties && mono_array_length (tb->properties)) {
3499 table = &assembly->tables [MONO_TABLE_PROPERTY];
3500 table->rows += mono_array_length (tb->properties);
3501 alloc_table (table, table->rows);
3502 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3504 alloc_table (table, table->rows);
3505 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3506 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3507 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3508 for (i = 0; i < mono_array_length (tb->properties); ++i)
3509 mono_image_get_property_info (
3510 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3513 /* handle generic parameters */
3514 if (tb->generic_params) {
3515 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3516 table->rows += mono_array_length (tb->generic_params);
3517 alloc_table (table, table->rows);
3518 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3519 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3521 mono_image_get_generic_param_info (
3522 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3526 mono_image_add_decl_security (assembly,
3527 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3530 MonoDynamicTable *ntable;
3532 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3533 ntable->rows += mono_array_length (tb->subtypes);
3534 alloc_table (ntable, ntable->rows);
3535 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3537 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3538 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3540 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3541 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3542 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3543 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3544 mono_string_to_utf8 (tb->name), tb->table_idx,
3545 ntable->next_idx, ntable->rows);*/
3546 values += MONO_NESTED_CLASS_SIZE;
3554 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3558 mono_ptr_array_append (*types, type);
3560 if (!type->subtypes)
3563 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3564 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3565 collect_types (types, subtype);
3570 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3572 if ((*type1)->table_idx < (*type2)->table_idx)
3575 if ((*type1)->table_idx > (*type2)->table_idx)
3582 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3587 for (i = 0; i < mono_array_length (pinfo); ++i) {
3588 MonoReflectionParamBuilder *pb;
3589 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3592 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3597 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3600 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3602 for (i = 0; i < tb->num_fields; ++i) {
3603 MonoReflectionFieldBuilder* fb;
3604 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3605 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3609 for (i = 0; i < mono_array_length (tb->events); ++i) {
3610 MonoReflectionEventBuilder* eb;
3611 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3612 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3615 if (tb->properties) {
3616 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3617 MonoReflectionPropertyBuilder* pb;
3618 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3619 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3623 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3624 MonoReflectionCtorBuilder* cb;
3625 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3626 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3627 params_add_cattrs (assembly, cb->pinfo);
3632 for (i = 0; i < tb->num_methods; ++i) {
3633 MonoReflectionMethodBuilder* mb;
3634 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3635 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3636 params_add_cattrs (assembly, mb->pinfo);
3641 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3642 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3647 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3651 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3653 if (moduleb->global_methods) {
3654 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3655 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3656 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3657 params_add_cattrs (assembly, mb->pinfo);
3661 if (moduleb->global_fields) {
3662 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3663 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3664 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3668 if (moduleb->types) {
3669 for (i = 0; i < moduleb->num_types; ++i)
3670 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3675 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3677 MonoDynamicTable *table;
3681 char *b = blob_size;
3684 table = &assembly->tables [MONO_TABLE_FILE];
3686 alloc_table (table, table->rows);
3687 values = table->values + table->next_idx * MONO_FILE_SIZE;
3688 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3689 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3690 if (module->image->dynamic) {
3691 /* This depends on the fact that the main module is emitted last */
3692 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3693 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3696 path = g_strdup (module->image->name);
3698 mono_sha1_get_digest_from_file (path, hash);
3701 mono_metadata_encode_value (20, b, &b);
3702 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3703 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3708 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3710 MonoDynamicTable *table;
3713 table = &assembly->tables [MONO_TABLE_MODULE];
3714 mb->table_idx = table->next_idx ++;
3715 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3716 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3719 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3720 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3721 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3722 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3726 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3727 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3729 MonoDynamicTable *table;
3733 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3734 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3737 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3739 alloc_table (table, table->rows);
3740 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3742 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3743 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3744 if (klass->nested_in)
3745 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3747 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3748 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3749 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3751 res = table->next_idx;
3755 /* Emit nested types */
3756 if (klass->ext && klass->ext->nested_classes) {
3759 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3760 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3767 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3768 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3773 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3775 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3777 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3778 parent_index, assembly);
3782 * We need to do this ourselves since klass->nested_classes is not set up.
3785 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3786 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3791 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3792 guint32 module_index, MonoDynamicImage *assembly)
3794 MonoImage *image = module->image;
3798 t = &image->tables [MONO_TABLE_TYPEDEF];
3800 for (i = 0; i < t->rows; ++i) {
3801 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3803 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3804 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3809 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3811 MonoDynamicTable *table;
3813 guint32 scope, scope_idx, impl, current_idx;
3814 gboolean forwarder = TRUE;
3815 gpointer iter = NULL;
3818 if (klass->nested_in) {
3819 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3822 scope = resolution_scope_from_image (assembly, klass->image);
3823 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3824 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3825 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3828 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3831 alloc_table (table, table->rows);
3832 current_idx = table->next_idx;
3833 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3835 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3836 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3837 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3838 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3839 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3843 while ((nested = mono_class_get_nested_types (klass, &iter)))
3844 add_exported_type (assemblyb, assembly, nested, current_idx);
3848 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3853 if (!assemblyb->type_forwarders)
3856 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3857 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3862 type = mono_reflection_type_get_handle (t);
3865 klass = mono_class_from_mono_type (type);
3867 add_exported_type (assemblyb, assembly, klass, 0);
3871 #define align_pointer(base,p)\
3873 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3875 (p) += 4 - (__diff & 3);\
3879 compare_constants (const void *a, const void *b)
3881 const guint32 *a_values = a;
3882 const guint32 *b_values = b;
3883 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3887 compare_semantics (const void *a, const void *b)
3889 const guint32 *a_values = a;
3890 const guint32 *b_values = b;
3891 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3894 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3898 compare_custom_attrs (const void *a, const void *b)
3900 const guint32 *a_values = a;
3901 const guint32 *b_values = b;
3903 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3907 compare_field_marshal (const void *a, const void *b)
3909 const guint32 *a_values = a;
3910 const guint32 *b_values = b;
3912 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3916 compare_nested (const void *a, const void *b)
3918 const guint32 *a_values = a;
3919 const guint32 *b_values = b;
3921 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3925 compare_genericparam (const void *a, const void *b)
3927 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3928 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3930 if ((*b_entry)->owner == (*a_entry)->owner)
3932 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3933 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3935 return (*a_entry)->owner - (*b_entry)->owner;
3939 compare_declsecurity_attrs (const void *a, const void *b)
3941 const guint32 *a_values = a;
3942 const guint32 *b_values = b;
3944 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3948 compare_interface_impl (const void *a, const void *b)
3950 const guint32 *a_values = a;
3951 const guint32 *b_values = b;
3953 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3957 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3961 pad_heap (MonoDynamicStream *sh)
3963 if (sh->index & 3) {
3964 int sz = 4 - (sh->index & 3);
3965 memset (sh->data + sh->index, 0, sz);
3972 MonoDynamicStream *stream;
3976 * build_compressed_metadata() fills in the blob of data that represents the
3977 * raw metadata as it will be saved in the PE file. The five streams are output
3978 * and the metadata tables are comnpressed from the guint32 array representation,
3979 * to the compressed on-disk format.
3982 build_compressed_metadata (MonoDynamicImage *assembly)
3984 MonoDynamicTable *table;
3986 guint64 valid_mask = 0;
3987 guint64 sorted_mask;
3988 guint32 heapt_size = 0;
3989 guint32 meta_size = 256; /* allow for header and other stuff */
3990 guint32 table_offset;
3991 guint32 ntables = 0;
3997 struct StreamDesc stream_desc [5];
3999 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4000 for (i = 0; i < assembly->gen_params->len; i++){
4001 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4002 write_generic_param_entry (assembly, entry);
4005 stream_desc [0].name = "#~";
4006 stream_desc [0].stream = &assembly->tstream;
4007 stream_desc [1].name = "#Strings";
4008 stream_desc [1].stream = &assembly->sheap;
4009 stream_desc [2].name = "#US";
4010 stream_desc [2].stream = &assembly->us;
4011 stream_desc [3].name = "#Blob";
4012 stream_desc [3].stream = &assembly->blob;
4013 stream_desc [4].name = "#GUID";
4014 stream_desc [4].stream = &assembly->guid;
4016 /* tables that are sorted */
4017 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4018 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4019 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4020 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4021 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4022 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4023 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4025 /* Compute table sizes */
4026 /* the MonoImage has already been created in mono_image_basic_init() */
4027 meta = &assembly->image;
4029 /* sizes should be multiple of 4 */
4030 pad_heap (&assembly->blob);
4031 pad_heap (&assembly->guid);
4032 pad_heap (&assembly->sheap);
4033 pad_heap (&assembly->us);
4035 /* Setup the info used by compute_sizes () */
4036 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4037 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4038 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4040 meta_size += assembly->blob.index;
4041 meta_size += assembly->guid.index;
4042 meta_size += assembly->sheap.index;
4043 meta_size += assembly->us.index;
4045 for (i=0; i < MONO_TABLE_NUM; ++i)
4046 meta->tables [i].rows = assembly->tables [i].rows;
4048 for (i = 0; i < MONO_TABLE_NUM; i++){
4049 if (meta->tables [i].rows == 0)
4051 valid_mask |= (guint64)1 << i;
4053 meta->tables [i].row_size = mono_metadata_compute_size (
4054 meta, i, &meta->tables [i].size_bitfield);
4055 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4057 heapt_size += 24; /* #~ header size */
4058 heapt_size += ntables * 4;
4059 /* make multiple of 4 */
4062 meta_size += heapt_size;
4063 meta->raw_metadata = g_malloc0 (meta_size);
4064 p = (unsigned char*)meta->raw_metadata;
4065 /* the metadata signature */
4066 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4067 /* version numbers and 4 bytes reserved */
4068 int16val = (guint16*)p;
4069 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4070 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4072 /* version string */
4073 int32val = (guint32*)p;
4074 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4076 memcpy (p, meta->version, strlen (meta->version));
4077 p += GUINT32_FROM_LE (*int32val);
4078 align_pointer (meta->raw_metadata, p);
4079 int16val = (guint16*)p;
4080 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4081 *int16val = GUINT16_TO_LE (5); /* number of streams */
4085 * write the stream info.
4087 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4088 table_offset += 3; table_offset &= ~3;
4090 assembly->tstream.index = heapt_size;
4091 for (i = 0; i < 5; ++i) {
4092 int32val = (guint32*)p;
4093 stream_desc [i].stream->offset = table_offset;
4094 *int32val++ = GUINT32_TO_LE (table_offset);
4095 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4096 table_offset += GUINT32_FROM_LE (*int32val);
4097 table_offset += 3; table_offset &= ~3;
4099 strcpy ((char*)p, stream_desc [i].name);
4100 p += strlen (stream_desc [i].name) + 1;
4101 align_pointer (meta->raw_metadata, p);
4104 * now copy the data, the table stream header and contents goes first.
4106 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4107 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4108 int32val = (guint32*)p;
4109 *int32val = GUINT32_TO_LE (0); /* reserved */
4112 *p++ = 2; /* version */
4115 if (meta->idx_string_wide)
4117 if (meta->idx_guid_wide)
4119 if (meta->idx_blob_wide)
4122 *p++ = 1; /* reserved */
4123 int64val = (guint64*)p;
4124 *int64val++ = GUINT64_TO_LE (valid_mask);
4125 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4127 int32val = (guint32*)p;
4128 for (i = 0; i < MONO_TABLE_NUM; i++){
4129 if (meta->tables [i].rows == 0)
4131 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4133 p = (unsigned char*)int32val;
4135 /* sort the tables that still need sorting */
4136 table = &assembly->tables [MONO_TABLE_CONSTANT];
4138 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4139 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4141 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4142 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4144 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4145 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4147 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4148 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4150 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4151 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4152 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4154 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4155 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4157 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4159 /* compress the tables */
4160 for (i = 0; i < MONO_TABLE_NUM; i++){
4163 guint32 bitfield = meta->tables [i].size_bitfield;
4164 if (!meta->tables [i].rows)
4166 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4167 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4168 meta->tables [i].base = (char*)p;
4169 for (row = 1; row <= meta->tables [i].rows; ++row) {
4170 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4171 for (col = 0; col < assembly->tables [i].columns; ++col) {
4172 switch (mono_metadata_table_size (bitfield, col)) {
4174 *p++ = values [col];
4177 *p++ = values [col] & 0xff;
4178 *p++ = (values [col] >> 8) & 0xff;
4181 *p++ = values [col] & 0xff;
4182 *p++ = (values [col] >> 8) & 0xff;
4183 *p++ = (values [col] >> 16) & 0xff;
4184 *p++ = (values [col] >> 24) & 0xff;
4187 g_assert_not_reached ();
4191 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4194 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4195 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4196 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4197 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4198 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4200 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4204 * Some tables in metadata need to be sorted according to some criteria, but
4205 * when methods and fields are first created with reflection, they may be assigned a token
4206 * that doesn't correspond to the final token they will get assigned after the sorting.
4207 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4208 * with the reflection objects that represent them. Once all the tables are set up, the
4209 * reflection objects will contains the correct table index. fixup_method() will fixup the
4210 * tokens for the method with ILGenerator @ilgen.
4213 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4215 guint32 code_idx = GPOINTER_TO_UINT (value);
4216 MonoReflectionILTokenInfo *iltoken;
4217 MonoReflectionFieldBuilder *field;
4218 MonoReflectionCtorBuilder *ctor;
4219 MonoReflectionMethodBuilder *method;
4220 MonoReflectionTypeBuilder *tb;
4221 MonoReflectionArrayMethod *am;
4223 unsigned char *target;
4225 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4226 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4227 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4228 switch (target [3]) {
4229 case MONO_TABLE_FIELD:
4230 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4231 field = (MonoReflectionFieldBuilder *)iltoken->member;
4232 idx = field->table_idx;
4233 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4234 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4235 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4237 g_assert_not_reached ();
4240 case MONO_TABLE_METHOD:
4241 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4242 method = (MonoReflectionMethodBuilder *)iltoken->member;
4243 idx = method->table_idx;
4244 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4245 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4246 idx = ctor->table_idx;
4247 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4248 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4249 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4250 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4252 g_assert_not_reached ();
4255 case MONO_TABLE_TYPEDEF:
4256 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4257 g_assert_not_reached ();
4258 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4259 idx = tb->table_idx;
4261 case MONO_TABLE_MEMBERREF:
4262 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4263 am = (MonoReflectionArrayMethod*)iltoken->member;
4264 idx = am->table_idx;
4265 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4266 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4267 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4268 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4269 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4270 g_assert (m->klass->generic_class || m->klass->generic_container);
4272 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4274 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4275 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4276 g_assert (is_field_on_inst (f));
4278 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4279 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4281 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4283 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4285 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4288 g_assert_not_reached ();
4291 case MONO_TABLE_METHODSPEC:
4292 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4293 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4294 g_assert (mono_method_signature (m)->generic_param_count);
4296 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4298 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4301 g_assert_not_reached ();
4305 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4307 target [0] = idx & 0xff;
4308 target [1] = (idx >> 8) & 0xff;
4309 target [2] = (idx >> 16) & 0xff;
4316 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4317 * value is not known when the table is emitted.
4320 fixup_cattrs (MonoDynamicImage *assembly)
4322 MonoDynamicTable *table;
4324 guint32 type, i, idx, token;
4327 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4329 for (i = 0; i < table->rows; ++i) {
4330 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4332 type = values [MONO_CUSTOM_ATTR_TYPE];
4333 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4334 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4335 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4336 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4339 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4340 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4341 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4342 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4343 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4344 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4345 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4346 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4353 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4355 MonoDynamicTable *table;
4358 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4360 alloc_table (table, table->rows);
4361 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4362 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4363 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4364 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4365 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4370 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4372 MonoDynamicTable *table;
4376 char *b = blob_size;
4378 guint32 idx, offset;
4380 if (rsrc->filename) {
4381 name = mono_string_to_utf8 (rsrc->filename);
4382 sname = g_path_get_basename (name);
4384 table = &assembly->tables [MONO_TABLE_FILE];
4386 alloc_table (table, table->rows);
4387 values = table->values + table->next_idx * MONO_FILE_SIZE;
4388 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4389 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4392 mono_sha1_get_digest_from_file (name, hash);
4393 mono_metadata_encode_value (20, b, &b);
4394 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4395 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4397 idx = table->next_idx++;
4399 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4405 data = mono_array_addr (rsrc->data, char, 0);
4406 len = mono_array_length (rsrc->data);
4412 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4413 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4414 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4415 mono_image_add_stream_data (&assembly->resources, data, len);
4419 * The entry should be emitted into the MANIFESTRESOURCE table of
4420 * the main module, but that needs to reference the FILE table
4421 * which isn't emitted yet.
4428 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4432 set_version_from_string (MonoString *version, guint32 *values)
4434 gchar *ver, *p, *str;
4437 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4438 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4439 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4440 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4443 ver = str = mono_string_to_utf8 (version);
4444 for (i = 0; i < 4; ++i) {
4445 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4451 /* handle Revision and Build */
4461 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4465 char *b = blob_size;
4470 len = mono_array_length (pkey);
4471 mono_metadata_encode_value (len, b, &b);
4472 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4473 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4475 assembly->public_key = g_malloc (len);
4476 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4477 assembly->public_key_len = len;
4479 /* Special case: check for ECMA key (16 bytes) */
4480 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4481 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4482 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4483 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4484 /* minimum key size (in 2.0) is 384 bits */
4485 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4487 /* FIXME - verifier */
4488 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4489 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4491 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4497 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4499 MonoDynamicTable *table;
4500 MonoDynamicImage *assembly;
4501 MonoReflectionAssemblyBuilder *assemblyb;
4505 guint32 module_index;
4507 assemblyb = moduleb->assemblyb;
4508 assembly = moduleb->dynamic_image;
4509 domain = mono_object_domain (assemblyb);
4511 /* Emit ASSEMBLY table */
4512 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4513 alloc_table (table, 1);
4514 values = table->values + MONO_ASSEMBLY_SIZE;
4515 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4516 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4517 if (assemblyb->culture) {
4518 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4520 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4522 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4523 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4524 set_version_from_string (assemblyb->version, values);
4526 /* Emit FILE + EXPORTED_TYPE table */
4528 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4530 MonoReflectionModuleBuilder *file_module =
4531 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4532 if (file_module != moduleb) {
4533 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4535 if (file_module->types) {
4536 for (j = 0; j < file_module->num_types; ++j) {
4537 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4538 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4543 if (assemblyb->loaded_modules) {
4544 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4545 MonoReflectionModule *file_module =
4546 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4547 mono_image_fill_file_table (domain, file_module, assembly);
4549 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4552 if (assemblyb->type_forwarders)
4553 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4555 /* Emit MANIFESTRESOURCE table */
4557 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4559 MonoReflectionModuleBuilder *file_module =
4560 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4561 /* The table for the main module is emitted later */
4562 if (file_module != moduleb) {
4564 if (file_module->resources) {
4565 int len = mono_array_length (file_module->resources);
4566 for (j = 0; j < len; ++j) {
4567 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4568 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4575 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4578 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4579 * for the modulebuilder @moduleb.
4580 * At the end of the process, method and field tokens are fixed up and the
4581 * on-disk compressed metadata representation is created.
4584 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4586 MonoDynamicTable *table;
4587 MonoDynamicImage *assembly;
4588 MonoReflectionAssemblyBuilder *assemblyb;
4594 assemblyb = moduleb->assemblyb;
4595 assembly = moduleb->dynamic_image;
4596 domain = mono_object_domain (assemblyb);
4598 if (assembly->text_rva)
4601 assembly->text_rva = START_TEXT_RVA;
4603 if (moduleb->is_main) {
4604 mono_image_emit_manifest (moduleb);
4607 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4608 table->rows = 1; /* .<Module> */
4610 alloc_table (table, table->rows);
4612 * Set the first entry.
4614 values = table->values + table->columns;
4615 values [MONO_TYPEDEF_FLAGS] = 0;
4616 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4617 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4618 values [MONO_TYPEDEF_EXTENDS] = 0;
4619 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4620 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4623 * handle global methods
4624 * FIXME: test what to do when global methods are defined in multiple modules.
4626 if (moduleb->global_methods) {
4627 table = &assembly->tables [MONO_TABLE_METHOD];
4628 table->rows += mono_array_length (moduleb->global_methods);
4629 alloc_table (table, table->rows);
4630 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4631 mono_image_get_method_info (
4632 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4634 if (moduleb->global_fields) {
4635 table = &assembly->tables [MONO_TABLE_FIELD];
4636 table->rows += mono_array_length (moduleb->global_fields);
4637 alloc_table (table, table->rows);
4638 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4639 mono_image_get_field_info (
4640 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4643 table = &assembly->tables [MONO_TABLE_MODULE];
4644 alloc_table (table, 1);
4645 mono_image_fill_module_table (domain, moduleb, assembly);
4647 /* Collect all types into a list sorted by their table_idx */
4648 mono_ptr_array_init (types, moduleb->num_types);
4651 for (i = 0; i < moduleb->num_types; ++i) {
4652 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4653 collect_types (&types, type);
4656 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4657 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4658 table->rows += mono_ptr_array_size (types);
4659 alloc_table (table, table->rows);
4662 * Emit type names + namespaces at one place inside the string heap,
4663 * so load_class_names () needs to touch fewer pages.
4665 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4666 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4667 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4669 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4671 string_heap_insert_mstring (&assembly->sheap, tb->name);
4674 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4675 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4676 mono_image_get_type_info (domain, type, assembly);
4680 * table->rows is already set above and in mono_image_fill_module_table.
4682 /* add all the custom attributes at the end, once all the indexes are stable */
4683 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4685 /* CAS assembly permissions */
4686 if (assemblyb->permissions_minimum)
4687 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4688 if (assemblyb->permissions_optional)
4689 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4690 if (assemblyb->permissions_refused)
4691 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4693 module_add_cattrs (assembly, moduleb);
4696 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4698 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4699 * the final tokens and don't need another fixup pass. */
4701 if (moduleb->global_methods) {
4702 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4703 MonoReflectionMethodBuilder *mb = mono_array_get (
4704 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4705 mono_image_add_methodimpl (assembly, mb);
4709 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4710 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4711 if (type->methods) {
4712 for (j = 0; j < type->num_methods; ++j) {
4713 MonoReflectionMethodBuilder *mb = mono_array_get (
4714 type->methods, MonoReflectionMethodBuilder*, j);
4716 mono_image_add_methodimpl (assembly, mb);
4721 mono_ptr_array_destroy (types);
4723 fixup_cattrs (assembly);
4726 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4729 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4731 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4734 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4738 guint32 import_lookup_table;
4742 guint32 import_address_table_rva;
4750 #ifndef DISABLE_REFLECTION_EMIT
4753 * mono_image_insert_string:
4754 * @module: module builder object
4757 * Insert @str into the user string stream of @module.
4760 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4762 MonoDynamicImage *assembly;
4767 MONO_ARCH_SAVE_REGS;
4769 if (!module->dynamic_image)
4770 mono_image_module_basic_init (module);
4772 assembly = module->dynamic_image;
4774 if (assembly->save) {
4775 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4776 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4777 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4779 char *swapped = g_malloc (2 * mono_string_length (str));
4780 const char *p = (const char*)mono_string_chars (str);
4782 swap_with_size (swapped, p, 2, mono_string_length (str));
4783 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4787 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4789 mono_image_add_stream_data (&assembly->us, "", 1);
4791 idx = assembly->us.index ++;
4794 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4796 return MONO_TOKEN_STRING | idx;
4800 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4804 MonoMethodSignature *sig;
4806 klass = obj->vtable->klass;
4807 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4808 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4809 MonoMethodSignature *old;
4810 guint32 sig_token, parent;
4813 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4815 nargs = mono_array_length (opt_param_types);
4816 old = mono_method_signature (method);
4817 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4819 sig->hasthis = old->hasthis;
4820 sig->explicit_this = old->explicit_this;
4821 sig->call_convention = old->call_convention;
4822 sig->generic_param_count = old->generic_param_count;
4823 sig->param_count = old->param_count + nargs;
4824 sig->sentinelpos = old->param_count;
4825 sig->ret = old->ret;
4827 for (i = 0; i < old->param_count; i++)
4828 sig->params [i] = old->params [i];
4830 for (i = 0; i < nargs; i++) {
4831 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4832 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4835 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4836 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4837 parent >>= MONO_TYPEDEFORREF_BITS;
4839 parent <<= MONO_MEMBERREF_PARENT_BITS;
4840 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4842 sig_token = method_encode_signature (assembly, sig);
4843 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4844 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4845 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4846 ReflectionMethodBuilder rmb;
4847 guint32 parent, sig_token;
4848 int nopt_args, nparams, ngparams, i;
4851 reflection_methodbuilder_from_method_builder (&rmb, mb);
4852 rmb.opt_types = opt_param_types;
4853 nopt_args = mono_array_length (opt_param_types);
4855 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4856 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4857 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4859 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4860 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4861 sig->call_convention = rmb.call_conv;
4862 sig->generic_param_count = ngparams;
4863 sig->param_count = nparams + nopt_args;
4864 sig->sentinelpos = nparams;
4865 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4867 for (i = 0; i < nparams; i++) {
4868 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4869 sig->params [i] = mono_reflection_type_get_handle (rt);
4872 for (i = 0; i < nopt_args; i++) {
4873 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4874 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4877 sig_token = method_builder_encode_signature (assembly, &rmb);
4879 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4880 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4882 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4883 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4885 name = mono_string_to_utf8 (rmb.name);
4886 token = mono_image_get_varargs_method_token (
4887 assembly, parent, name, sig_token);
4890 g_error ("requested method token for %s\n", klass->name);
4893 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4894 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4899 * mono_image_create_token:
4900 * @assembly: a dynamic assembly
4902 * @register_token: Whenever to register the token in the assembly->tokens hash.
4904 * Get a token to insert in the IL code stream for the given MemberInfo.
4905 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4906 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4910 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4911 gboolean create_open_instance, gboolean register_token)
4916 klass = obj->vtable->klass;
4918 /* Check for user defined reflection objects */
4919 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4920 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4921 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4923 if (strcmp (klass->name, "MethodBuilder") == 0) {
4924 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4925 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4927 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4928 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4930 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4931 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4932 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4933 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4934 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4936 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4937 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4939 token = mono_image_get_ctorbuilder_token (assembly, mb);
4940 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4941 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4942 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4943 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4944 if (tb->generic_params) {
4945 token = mono_image_get_generic_field_token (assembly, fb);
4947 if (tb->module->dynamic_image == assembly) {
4948 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4950 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4953 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4954 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4955 if (create_open_instance && tb->generic_params) {
4957 init_type_builder_generics (obj);
4958 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4959 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4960 token = mono_metadata_token_from_dor (token);
4961 } else if (tb->module->dynamic_image == assembly) {
4962 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4965 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4966 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4968 } else if (strcmp (klass->name, "MonoType") == 0) {
4969 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4970 MonoClass *mc = mono_class_from_mono_type (type);
4971 token = mono_metadata_token_from_dor (
4972 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4973 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4974 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4975 token = mono_metadata_token_from_dor (
4976 mono_image_typedef_or_ref (assembly, type));
4977 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4978 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979 token = mono_metadata_token_from_dor (
4980 mono_image_typedef_or_ref (assembly, type));
4981 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4982 strcmp (klass->name, "MonoMethod") == 0 ||
4983 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4984 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4985 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4986 if (m->method->is_inflated) {
4987 if (create_open_instance)
4988 token = mono_image_get_methodspec_token (assembly, m->method);
4990 token = mono_image_get_inflated_method_token (assembly, m->method);
4991 } else if ((m->method->klass->image == &assembly->image) &&
4992 !m->method->klass->generic_class) {
4993 static guint32 method_table_idx = 0xffffff;
4994 if (m->method->klass->wastypebuilder) {
4995 /* we use the same token as the one that was assigned
4996 * to the Methodbuilder.
4997 * FIXME: do the equivalent for Fields.
4999 token = m->method->token;
5002 * Each token should have a unique index, but the indexes are
5003 * assigned by managed code, so we don't know about them. An
5004 * easy solution is to count backwards...
5006 method_table_idx --;
5007 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5010 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5012 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5013 } else if (strcmp (klass->name, "MonoField") == 0) {
5014 MonoReflectionField *f = (MonoReflectionField *)obj;
5015 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5016 static guint32 field_table_idx = 0xffffff;
5018 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5020 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5022 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5023 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5024 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5025 token = mono_image_get_array_token (assembly, m);
5026 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5027 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5028 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5029 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5030 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5031 token = mono_metadata_token_from_dor (
5032 mono_image_typedef_or_ref (assembly, type));
5033 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5034 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5035 token = mono_image_get_field_on_inst_token (assembly, f);
5036 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5037 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5038 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5039 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5040 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5041 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5042 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5043 MonoReflectionType *type = (MonoReflectionType *)obj;
5044 token = mono_metadata_token_from_dor (
5045 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5047 g_error ("requested token for %s\n", klass->name);
5051 mono_image_register_token (assembly, token, obj);
5057 * mono_image_register_token:
5059 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5060 * the Module.ResolveXXXToken () methods to work.
5063 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5065 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5067 /* There could be multiple MethodInfo objects with the same token */
5068 //g_assert (prev == obj);
5070 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5074 static MonoDynamicImage*
5075 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5077 static const guchar entrycode [16] = {0xff, 0x25, 0};
5078 MonoDynamicImage *image;
5081 const char *version;
5083 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5084 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5086 version = mono_get_runtime_info ()->runtime_version;
5089 /* The MonoGHashTable's need GC tracking */
5090 image = GC_MALLOC (sizeof (MonoDynamicImage));
5092 image = g_new0 (MonoDynamicImage, 1);
5095 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5097 /*g_print ("created image %p\n", image);*/
5098 /* keep in sync with image.c */
5099 image->image.name = assembly_name;
5100 image->image.assembly_name = image->image.name; /* they may be different */
5101 image->image.module_name = module_name;
5102 image->image.version = g_strdup (version);
5103 image->image.md_version_major = 1;
5104 image->image.md_version_minor = 1;
5105 image->image.dynamic = TRUE;
5107 image->image.references = g_new0 (MonoAssembly*, 1);
5108 image->image.references [0] = NULL;
5110 mono_image_init (&image->image);
5112 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5113 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5114 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5115 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5116 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5117 image->handleref = g_hash_table_new (NULL, NULL);
5118 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5119 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5120 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5122 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5123 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5125 image->gen_params = g_ptr_array_new ();
5126 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5128 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5129 string_heap_init (&image->sheap);
5130 mono_image_add_stream_data (&image->us, "", 1);
5131 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5132 /* import tables... */
5133 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5134 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5135 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5136 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5137 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5138 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5139 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5140 stream_data_align (&image->code);
5142 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5144 for (i=0; i < MONO_TABLE_NUM; ++i) {
5145 image->tables [i].next_idx = 1;
5146 image->tables [i].columns = table_sizes [i];
5149 image->image.assembly = (MonoAssembly*)assembly;
5150 image->run = assembly->run;
5151 image->save = assembly->save;
5152 image->pe_kind = 0x1; /* ILOnly */
5153 image->machine = 0x14c; /* I386 */
5155 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5162 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5168 release_hashtable (MonoGHashTable **hash)
5171 mono_g_hash_table_destroy (*hash);
5177 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5179 release_hashtable (&image->token_fixups);
5180 release_hashtable (&image->handleref_managed);
5181 release_hashtable (&image->tokens);
5182 release_hashtable (&image->remapped_tokens);
5183 release_hashtable (&image->generic_def_objects);
5184 release_hashtable (&image->methodspec);
5188 mono_dynamic_image_free (MonoDynamicImage *image)
5190 MonoDynamicImage *di = image;
5195 mono_g_hash_table_destroy (di->methodspec);
5197 g_hash_table_destroy (di->typespec);
5199 g_hash_table_destroy (di->typeref);
5201 g_hash_table_destroy (di->handleref);
5202 if (di->handleref_managed)
5203 mono_g_hash_table_destroy (di->handleref_managed);
5205 mono_g_hash_table_destroy (di->tokens);
5206 if (di->remapped_tokens)
5207 mono_g_hash_table_destroy (di->remapped_tokens);
5208 if (di->generic_def_objects)
5209 mono_g_hash_table_destroy (di->generic_def_objects);
5210 if (di->blob_cache) {
5211 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5212 g_hash_table_destroy (di->blob_cache);
5214 if (di->standalonesig_cache)
5215 g_hash_table_destroy (di->standalonesig_cache);
5216 for (list = di->array_methods; list; list = list->next) {
5217 ArrayMethod *am = (ArrayMethod *)list->data;
5222 g_list_free (di->array_methods);
5223 if (di->gen_params) {
5224 for (i = 0; i < di->gen_params->len; i++) {
5225 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5226 mono_gc_deregister_root ((char*) &entry->gparam);
5229 g_ptr_array_free (di->gen_params, TRUE);
5231 if (di->token_fixups)
5232 mono_g_hash_table_destroy (di->token_fixups);
5233 if (di->method_to_table_idx)
5234 g_hash_table_destroy (di->method_to_table_idx);
5235 if (di->field_to_table_idx)
5236 g_hash_table_destroy (di->field_to_table_idx);
5237 if (di->method_aux_hash)
5238 g_hash_table_destroy (di->method_aux_hash);
5239 if (di->vararg_aux_hash)
5240 g_hash_table_destroy (di->vararg_aux_hash);
5241 g_free (di->strong_name);
5242 g_free (di->win32_res);
5244 g_free (di->public_key);
5246 /*g_print ("string heap destroy for image %p\n", di);*/
5247 mono_dynamic_stream_reset (&di->sheap);
5248 mono_dynamic_stream_reset (&di->code);
5249 mono_dynamic_stream_reset (&di->resources);
5250 mono_dynamic_stream_reset (&di->us);
5251 mono_dynamic_stream_reset (&di->blob);
5252 mono_dynamic_stream_reset (&di->tstream);
5253 mono_dynamic_stream_reset (&di->guid);
5254 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5255 g_free (di->tables [i].values);
5260 mono_dynamic_image_free_image (MonoDynamicImage *image)
5262 /* See create_dynamic_mono_image () */
5264 /* Allocated using GC_MALLOC */
5270 #ifndef DISABLE_REFLECTION_EMIT
5273 * mono_image_basic_init:
5274 * @assembly: an assembly builder object
5276 * Create the MonoImage that represents the assembly builder and setup some
5277 * of the helper hash table and the basic metadata streams.
5280 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5282 MonoDynamicAssembly *assembly;
5283 MonoDynamicImage *image;
5284 MonoDomain *domain = mono_object_domain (assemblyb);
5286 MONO_ARCH_SAVE_REGS;
5288 if (assemblyb->dynamic_assembly)
5292 /* assembly->assembly.image might be GC allocated */
5293 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5295 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5298 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5300 assembly->assembly.ref_count = 1;
5301 assembly->assembly.dynamic = TRUE;
5302 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5303 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5304 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5305 if (assemblyb->culture)
5306 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5308 assembly->assembly.aname.culture = g_strdup ("");
5310 if (assemblyb->version) {
5311 char *vstr = mono_string_to_utf8 (assemblyb->version);
5312 char **version = g_strsplit (vstr, ".", 4);
5313 char **parts = version;
5314 assembly->assembly.aname.major = atoi (*parts++);
5315 assembly->assembly.aname.minor = atoi (*parts++);
5316 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5317 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5319 g_strfreev (version);
5322 assembly->assembly.aname.major = 0;
5323 assembly->assembly.aname.minor = 0;
5324 assembly->assembly.aname.build = 0;
5325 assembly->assembly.aname.revision = 0;
5328 assembly->run = assemblyb->access != 2;
5329 assembly->save = assemblyb->access != 1;
5330 assembly->domain = domain;
5332 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5333 image->initial_image = TRUE;
5334 assembly->assembly.aname.name = image->image.name;
5335 assembly->assembly.image = &image->image;
5336 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5337 /* -1 to correct for the trailing NULL byte */
5338 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5339 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5341 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5344 mono_domain_assemblies_lock (domain);
5345 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5346 mono_domain_assemblies_unlock (domain);
5348 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5350 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5352 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5355 #endif /* !DISABLE_REFLECTION_EMIT */
5357 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5360 calc_section_size (MonoDynamicImage *assembly)
5364 /* alignment constraints */
5365 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5366 g_assert ((assembly->code.index % 4) == 0);
5367 assembly->meta_size += 3;
5368 assembly->meta_size &= ~3;
5369 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5370 g_assert ((assembly->resources.index % 4) == 0);
5372 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5373 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5376 if (assembly->win32_res) {
5377 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5379 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5380 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5384 assembly->sections [MONO_SECTION_RELOC].size = 12;
5385 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5395 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5399 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5401 ResTreeNode *t1 = (ResTreeNode*)a;
5402 ResTreeNode *t2 = (ResTreeNode*)b;
5404 return t1->id - t2->id;
5408 * resource_tree_create:
5410 * Organize the resources into a resource tree.
5412 static ResTreeNode *
5413 resource_tree_create (MonoArray *win32_resources)
5415 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5419 tree = g_new0 (ResTreeNode, 1);
5421 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5422 MonoReflectionWin32Resource *win32_res =
5423 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5427 /* FIXME: BUG: this stores managed references in unmanaged memory */
5428 lang_node = g_new0 (ResTreeNode, 1);
5429 lang_node->id = win32_res->lang_id;
5430 lang_node->win32_res = win32_res;
5432 /* Create type node if neccesary */
5434 for (l = tree->children; l; l = l->next)
5435 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5436 type_node = (ResTreeNode*)l->data;
5441 type_node = g_new0 (ResTreeNode, 1);
5442 type_node->id = win32_res->res_type;
5445 * The resource types have to be sorted otherwise
5446 * Windows Explorer can't display the version information.
5448 tree->children = g_slist_insert_sorted (tree->children,
5449 type_node, resource_tree_compare_by_id);
5452 /* Create res node if neccesary */
5454 for (l = type_node->children; l; l = l->next)
5455 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5456 res_node = (ResTreeNode*)l->data;
5461 res_node = g_new0 (ResTreeNode, 1);
5462 res_node->id = win32_res->res_id;
5463 type_node->children = g_slist_append (type_node->children, res_node);
5466 res_node->children = g_slist_append (res_node->children, lang_node);
5473 * resource_tree_encode:
5475 * Encode the resource tree into the format used in the PE file.
5478 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5481 MonoPEResourceDir dir;
5482 MonoPEResourceDirEntry dir_entry;
5483 MonoPEResourceDataEntry data_entry;
5485 guint32 res_id_entries;
5488 * For the format of the resource directory, see the article
5489 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5493 memset (&dir, 0, sizeof (dir));
5494 memset (&dir_entry, 0, sizeof (dir_entry));
5495 memset (&data_entry, 0, sizeof (data_entry));
5497 g_assert (sizeof (dir) == 16);
5498 g_assert (sizeof (dir_entry) == 8);
5499 g_assert (sizeof (data_entry) == 16);
5501 node->offset = p - begin;
5503 /* IMAGE_RESOURCE_DIRECTORY */
5504 res_id_entries = g_slist_length (node->children);
5505 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5507 memcpy (p, &dir, sizeof (dir));
5510 /* Reserve space for entries */
5512 p += sizeof (dir_entry) * res_id_entries;
5514 /* Write children */
5515 for (l = node->children; l; l = l->next) {
5516 ResTreeNode *child = (ResTreeNode*)l->data;
5518 if (child->win32_res) {
5521 child->offset = p - begin;
5523 /* IMAGE_RESOURCE_DATA_ENTRY */
5524 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5525 size = mono_array_length (child->win32_res->res_data);
5526 data_entry.rde_size = GUINT32_TO_LE (size);
5528 memcpy (p, &data_entry, sizeof (data_entry));
5529 p += sizeof (data_entry);
5531 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5534 resource_tree_encode (child, begin, p, &p);
5538 /* IMAGE_RESOURCE_ENTRY */
5539 for (l = node->children; l; l = l->next) {
5540 ResTreeNode *child = (ResTreeNode*)l->data;
5542 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5543 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5545 memcpy (entries, &dir_entry, sizeof (dir_entry));
5546 entries += sizeof (dir_entry);
5553 resource_tree_free (ResTreeNode * node)
5556 for (list = node->children; list; list = list->next)
5557 resource_tree_free ((ResTreeNode*)list->data);
5558 g_slist_free(node->children);
5563 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5568 MonoReflectionWin32Resource *win32_res;
5571 if (!assemblyb->win32_resources)
5575 * Resources are stored in a three level tree inside the PE file.
5576 * - level one contains a node for each type of resource
5577 * - level two contains a node for each resource
5578 * - level three contains a node for each instance of a resource for a
5579 * specific language.
5582 tree = resource_tree_create (assemblyb->win32_resources);
5584 /* Estimate the size of the encoded tree */
5586 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5587 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5588 size += mono_array_length (win32_res->res_data);
5590 /* Directory structure */
5591 size += mono_array_length (assemblyb->win32_resources) * 256;
5592 p = buf = g_malloc (size);
5594 resource_tree_encode (tree, p, p, &p);
5596 g_assert (p - buf <= size);
5598 assembly->win32_res = g_malloc (p - buf);
5599 assembly->win32_res_size = p - buf;
5600 memcpy (assembly->win32_res, buf, p - buf);
5603 resource_tree_free (tree);
5607 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5609 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5612 p += sizeof (MonoPEResourceDir);
5613 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5614 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5615 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5616 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5617 fixup_resource_directory (res_section, child, rva);
5619 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5620 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5623 p += sizeof (MonoPEResourceDirEntry);
5628 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5631 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5632 g_error ("WriteFile returned %d\n", GetLastError ());
5636 * mono_image_create_pefile:
5637 * @mb: a module builder object
5639 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5640 * assembly->pefile where it can be easily retrieved later in chunks.
5643 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5645 MonoMSDOSHeader *msdos;
5646 MonoDotNetHeader *header;
5647 MonoSectionTable *section;
5648 MonoCLIHeader *cli_header;
5649 guint32 size, image_size, virtual_base, text_offset;
5650 guint32 header_start, section_start, file_offset, virtual_offset;
5651 MonoDynamicImage *assembly;
5652 MonoReflectionAssemblyBuilder *assemblyb;
5653 MonoDynamicStream pefile_stream = {0};
5654 MonoDynamicStream *pefile = &pefile_stream;
5656 guint32 *rva, value;
5658 static const unsigned char msheader[] = {
5659 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5660 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5663 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5664 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5665 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5666 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5669 assemblyb = mb->assemblyb;
5671 mono_image_basic_init (assemblyb);
5672 assembly = mb->dynamic_image;
5674 assembly->pe_kind = assemblyb->pe_kind;
5675 assembly->machine = assemblyb->machine;
5676 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5677 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5679 mono_image_build_metadata (mb);
5681 if (mb->is_main && assemblyb->resources) {
5682 int len = mono_array_length (assemblyb->resources);
5683 for (i = 0; i < len; ++i)
5684 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5687 if (mb->resources) {
5688 int len = mono_array_length (mb->resources);
5689 for (i = 0; i < len; ++i)
5690 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5693 build_compressed_metadata (assembly);
5696 assembly_add_win32_resources (assembly, assemblyb);
5698 nsections = calc_section_size (assembly);
5700 /* The DOS header and stub */
5701 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5702 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5704 /* the dotnet header */
5705 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5707 /* the section tables */
5708 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5710 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5711 virtual_offset = VIRT_ALIGN;
5714 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5715 if (!assembly->sections [i].size)
5718 file_offset += FILE_ALIGN - 1;
5719 file_offset &= ~(FILE_ALIGN - 1);
5720 virtual_offset += VIRT_ALIGN - 1;
5721 virtual_offset &= ~(VIRT_ALIGN - 1);
5723 assembly->sections [i].offset = file_offset;
5724 assembly->sections [i].rva = virtual_offset;
5726 file_offset += assembly->sections [i].size;
5727 virtual_offset += assembly->sections [i].size;
5728 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5731 file_offset += FILE_ALIGN - 1;
5732 file_offset &= ~(FILE_ALIGN - 1);
5734 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5736 /* back-patch info */
5737 msdos = (MonoMSDOSHeader*)pefile->data;
5738 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5740 header = (MonoDotNetHeader*)(pefile->data + header_start);
5741 header->pesig [0] = 'P';
5742 header->pesig [1] = 'E';
5744 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5745 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5746 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5747 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5748 if (assemblyb->pekind == 1) {
5750 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5753 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5756 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5758 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5759 header->pe.pe_major = 6;
5760 header->pe.pe_minor = 0;
5761 size = assembly->sections [MONO_SECTION_TEXT].size;
5762 size += FILE_ALIGN - 1;
5763 size &= ~(FILE_ALIGN - 1);
5764 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5765 size = assembly->sections [MONO_SECTION_RSRC].size;
5766 size += FILE_ALIGN - 1;
5767 size &= ~(FILE_ALIGN - 1);
5768 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5769 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5770 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5771 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5772 /* pe_rva_entry_point always at the beginning of the text section */
5773 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5775 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5776 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5777 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5778 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5779 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5780 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5781 size = section_start;
5782 size += FILE_ALIGN - 1;
5783 size &= ~(FILE_ALIGN - 1);
5784 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5786 size += VIRT_ALIGN - 1;
5787 size &= ~(VIRT_ALIGN - 1);
5788 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5791 // Translate the PEFileKind value to the value expected by the Windows loader
5797 // PEFileKinds.Dll == 1
5798 // PEFileKinds.ConsoleApplication == 2
5799 // PEFileKinds.WindowApplication == 3
5802 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5803 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5805 if (assemblyb->pekind == 3)
5810 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5812 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5813 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5814 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5815 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5816 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5817 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5819 /* fill data directory entries */
5821 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5822 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5824 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5825 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5827 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5828 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5829 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5830 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5831 /* patch entrypoint name */
5832 if (assemblyb->pekind == 1)
5833 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5835 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5836 /* patch imported function RVA name */
5837 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5838 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5840 /* the import table */
5841 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5842 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5843 /* patch imported dll RVA name and other entries in the dir */
5844 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5845 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5846 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5847 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5848 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5849 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5851 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5852 value = (assembly->text_rva + assembly->imp_names_offset);
5853 *p++ = (value) & 0xff;
5854 *p++ = (value >> 8) & (0xff);
5855 *p++ = (value >> 16) & (0xff);
5856 *p++ = (value >> 24) & (0xff);
5858 /* the CLI header info */
5859 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5860 cli_header->ch_size = GUINT32_FROM_LE (72);
5861 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5862 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5863 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5864 if (assemblyb->entry_point) {
5865 guint32 table_idx = 0;
5866 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5867 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5868 table_idx = methodb->table_idx;
5870 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5872 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5874 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5876 /* The embedded managed resources */
5877 text_offset = assembly->text_rva + assembly->code.index;
5878 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5879 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5880 text_offset += assembly->resources.index;
5881 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5882 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5883 text_offset += assembly->meta_size;
5884 if (assembly->strong_name_size) {
5885 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5886 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5887 text_offset += assembly->strong_name_size;
5890 /* write the section tables and section content */
5891 section = (MonoSectionTable*)(pefile->data + section_start);
5892 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5893 static const char section_names [][7] = {
5894 ".text", ".rsrc", ".reloc"
5896 if (!assembly->sections [i].size)
5898 strcpy (section->st_name, section_names [i]);
5899 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5900 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5901 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5902 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5903 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5904 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5905 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5909 checked_write_file (file, pefile->data, pefile->index);
5911 mono_dynamic_stream_reset (pefile);
5913 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5914 if (!assembly->sections [i].size)
5917 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5918 g_error ("SetFilePointer returned %d\n", GetLastError ());
5921 case MONO_SECTION_TEXT:
5922 /* patch entry point */
5923 p = (guchar*)(assembly->code.data + 2);
5924 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5925 *p++ = (value) & 0xff;
5926 *p++ = (value >> 8) & 0xff;
5927 *p++ = (value >> 16) & 0xff;
5928 *p++ = (value >> 24) & 0xff;
5930 checked_write_file (file, assembly->code.data, assembly->code.index);
5931 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5932 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5933 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5936 g_free (assembly->image.raw_metadata);
5938 case MONO_SECTION_RELOC: {
5942 guint16 type_and_offset;
5946 g_assert (sizeof (reloc) == 12);
5948 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5949 reloc.block_size = GUINT32_FROM_LE (12);
5952 * the entrypoint is always at the start of the text section
5953 * 3 is IMAGE_REL_BASED_HIGHLOW
5954 * 2 is patch_size_rva - text_rva
5956 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5959 checked_write_file (file, &reloc, sizeof (reloc));
5963 case MONO_SECTION_RSRC:
5964 if (assembly->win32_res) {
5966 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5967 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5968 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5972 g_assert_not_reached ();
5976 /* check that the file is properly padded */
5977 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5978 g_error ("SetFilePointer returned %d\n", GetLastError ());
5979 if (! SetEndOfFile (file))
5980 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5982 mono_dynamic_stream_reset (&assembly->code);
5983 mono_dynamic_stream_reset (&assembly->us);
5984 mono_dynamic_stream_reset (&assembly->blob);
5985 mono_dynamic_stream_reset (&assembly->guid);
5986 mono_dynamic_stream_reset (&assembly->sheap);
5988 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5989 g_hash_table_destroy (assembly->blob_cache);
5990 assembly->blob_cache = NULL;
5993 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5996 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5998 g_assert_not_reached ();
6001 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6003 #ifndef DISABLE_REFLECTION_EMIT
6005 MonoReflectionModule *
6006 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6010 MonoImageOpenStatus status;
6011 MonoDynamicAssembly *assembly;
6012 guint32 module_count;
6013 MonoImage **new_modules;
6014 gboolean *new_modules_loaded;
6016 name = mono_string_to_utf8 (fileName);
6018 image = mono_image_open (name, &status);
6021 if (status == MONO_IMAGE_ERROR_ERRNO)
6022 exc = mono_get_exception_file_not_found (fileName);
6024 exc = mono_get_exception_bad_image_format (name);
6026 mono_raise_exception (exc);
6031 assembly = ab->dynamic_assembly;
6032 image->assembly = (MonoAssembly*)assembly;
6034 module_count = image->assembly->image->module_count;
6035 new_modules = g_new0 (MonoImage *, module_count + 1);
6036 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6038 if (image->assembly->image->modules)
6039 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6040 if (image->assembly->image->modules_loaded)
6041 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6042 new_modules [module_count] = image;
6043 new_modules_loaded [module_count] = TRUE;
6044 mono_image_addref (image);
6046 g_free (image->assembly->image->modules);
6047 image->assembly->image->modules = new_modules;
6048 image->assembly->image->modules_loaded = new_modules_loaded;
6049 image->assembly->image->module_count ++;
6051 mono_assembly_load_references (image, &status);
6053 mono_image_close (image);
6054 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6057 return mono_module_get_object (mono_domain_get (), image);
6060 #endif /* DISABLE_REFLECTION_EMIT */
6063 * We need to return always the same object for MethodInfo, FieldInfo etc..
6064 * but we need to consider the reflected type.
6065 * type uses a different hash, since it uses custom hash/equal functions.
6070 MonoClass *refclass;
6074 reflected_equal (gconstpointer a, gconstpointer b) {
6075 const ReflectedEntry *ea = a;
6076 const ReflectedEntry *eb = b;
6078 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6082 reflected_hash (gconstpointer a) {
6083 const ReflectedEntry *ea = a;
6084 return mono_aligned_addr_hash (ea->item);
6087 #define CHECK_OBJECT(t,p,k) \
6093 mono_domain_lock (domain); \
6094 if (!domain->refobject_hash) \
6095 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6096 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6097 mono_domain_unlock (domain); \
6100 mono_domain_unlock (domain); \
6103 #ifdef HAVE_BOEHM_GC
6104 /* ReflectedEntry doesn't need to be GC tracked */
6105 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6106 #define FREE_REFENTRY(entry) g_free ((entry))
6107 #define REFENTRY_REQUIRES_CLEANUP
6109 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6111 #define FREE_REFENTRY(entry)
6114 #define CACHE_OBJECT(t,p,o,k) \
6117 ReflectedEntry pe; \
6119 pe.refclass = (k); \
6120 mono_domain_lock (domain); \
6121 if (!domain->refobject_hash) \
6122 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6123 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6125 ReflectedEntry *e = ALLOC_REFENTRY; \
6127 e->refclass = (k); \
6128 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6131 mono_domain_unlock (domain); \
6136 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6138 mono_domain_lock (domain);
6139 if (domain->refobject_hash) {
6141 gpointer orig_pe, orig_value;
6144 pe.refclass = klass;
6145 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6146 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6147 FREE_REFENTRY (orig_pe);
6150 mono_domain_unlock (domain);
6153 #ifdef REFENTRY_REQUIRES_CLEANUP
6155 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6157 FREE_REFENTRY (key);
6162 mono_reflection_cleanup_domain (MonoDomain *domain)
6164 if (domain->refobject_hash) {
6165 /*let's avoid scanning the whole hashtable if not needed*/
6166 #ifdef REFENTRY_REQUIRES_CLEANUP
6167 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6169 mono_g_hash_table_destroy (domain->refobject_hash);
6170 domain->refobject_hash = NULL;
6174 #ifndef DISABLE_REFLECTION_EMIT
6176 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6178 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6182 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6184 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6188 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6190 MonoDynamicImage *image = moduleb->dynamic_image;
6191 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6195 MonoImage **new_modules;
6197 char *name, *fqname;
6199 * FIXME: we already created an image in mono_image_basic_init (), but
6200 * we don't know which module it belongs to, since that is only
6201 * determined at assembly save time.
6203 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6204 name = mono_string_to_utf8 (ab->name);
6205 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6206 if (!mono_error_ok (&error)) {
6208 mono_error_raise_exception (&error);
6210 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6212 moduleb->module.image = &image->image;
6213 moduleb->dynamic_image = image;
6214 register_module (mono_object_domain (moduleb), moduleb, image);
6216 /* register the module with the assembly */
6217 ass = ab->dynamic_assembly->assembly.image;
6218 module_count = ass->module_count;
6219 new_modules = g_new0 (MonoImage *, module_count + 1);
6222 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6223 new_modules [module_count] = &image->image;
6224 mono_image_addref (&image->image);
6226 g_free (ass->modules);
6227 ass->modules = new_modules;
6228 ass->module_count ++;
6233 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6235 MonoDynamicImage *image = moduleb->dynamic_image;
6237 g_assert (type->type);
6238 image->wrappers_type = mono_class_from_mono_type (type->type);
6244 * mono_assembly_get_object:
6245 * @domain: an app domain
6246 * @assembly: an assembly
6248 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6250 MonoReflectionAssembly*
6251 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6253 static MonoClass *assembly_type;
6254 MonoReflectionAssembly *res;
6256 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6257 if (!assembly_type) {
6258 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6260 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6262 assembly_type = class;
6264 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6265 res->assembly = assembly;
6267 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6272 MonoReflectionModule*
6273 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6275 static MonoClass *module_type;
6276 MonoReflectionModule *res;
6279 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6281 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6283 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6285 module_type = class;
6287 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6290 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6292 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6293 basename = g_path_get_basename (image->name);
6294 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6295 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6299 if (image->assembly->image == image) {
6300 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6304 if (image->assembly->image->modules) {
6305 for (i = 0; i < image->assembly->image->module_count; i++) {
6306 if (image->assembly->image->modules [i] == image)
6307 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6309 g_assert (res->token);
6313 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6316 MonoReflectionModule*
6317 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6319 static MonoClass *module_type;
6320 MonoReflectionModule *res;
6321 MonoTableInfo *table;
6322 guint32 cols [MONO_FILE_SIZE];
6324 guint32 i, name_idx;
6328 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6330 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6332 module_type = class;
6334 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6336 table = &image->tables [MONO_TABLE_FILE];
6337 g_assert (table_index < table->rows);
6338 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6341 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6342 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6344 /* Check whenever the row has a corresponding row in the moduleref table */
6345 table = &image->tables [MONO_TABLE_MODULEREF];
6346 for (i = 0; i < table->rows; ++i) {
6347 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6348 val = mono_metadata_string_heap (image, name_idx);
6349 if (strcmp (val, name) == 0)
6350 res->image = image->modules [i];
6353 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6354 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6355 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6356 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6357 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6363 verify_safe_for_managed_space (MonoType *type)
6365 switch (type->type) {
6367 case MONO_TYPE_ARRAY:
6368 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6370 return verify_safe_for_managed_space (type->data.type);
6371 case MONO_TYPE_SZARRAY:
6372 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6373 case MONO_TYPE_GENERICINST: {
6374 MonoGenericInst *inst = type->data.generic_class->inst;
6378 for (i = 0; i < inst->type_argc; ++i)
6379 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6385 case MONO_TYPE_MVAR:
6392 mono_type_normalize (MonoType *type)
6395 MonoGenericClass *gclass;
6396 MonoGenericInst *ginst;
6398 MonoGenericContainer *gcontainer;
6399 MonoType **argv = NULL;
6400 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6402 if (type->type != MONO_TYPE_GENERICINST)
6405 gclass = type->data.generic_class;
6406 ginst = gclass->context.class_inst;
6407 if (!ginst->is_open)
6410 gtd = gclass->container_class;
6411 gcontainer = gtd->generic_container;
6412 argv = g_newa (MonoType*, ginst->type_argc);
6414 for (i = 0; i < ginst->type_argc; ++i) {
6415 MonoType *t = ginst->type_argv [i], *norm;
6416 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6417 is_denorm_gtd = FALSE;
6418 norm = mono_type_normalize (t);
6421 requires_rebind = TRUE;
6425 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6427 if (requires_rebind) {
6428 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6429 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6435 * mono_type_get_object:
6436 * @domain: an app domain
6439 * Return an System.MonoType object representing the type @type.
6442 mono_type_get_object (MonoDomain *domain, MonoType *type)
6444 MonoType *norm_type;
6445 MonoReflectionType *res;
6446 MonoClass *klass = mono_class_from_mono_type (type);
6448 /*we must avoid using @type as it might have come
6449 * from a mono_metadata_type_dup and the caller
6450 * expects that is can be freed.
6451 * Using the right type from
6453 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6455 /* void is very common */
6456 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6457 return (MonoReflectionType*)domain->typeof_void;
6460 * If the vtable of the given class was already created, we can use
6461 * the MonoType from there and avoid all locking and hash table lookups.
6463 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6464 * that the resulting object is different.
6466 if (type == &klass->byval_arg && !klass->image->dynamic) {
6467 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6468 if (vtable && vtable->type)
6469 return vtable->type;
6472 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6473 mono_domain_lock (domain);
6474 if (!domain->type_hash)
6475 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6476 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6477 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6478 mono_domain_unlock (domain);
6479 mono_loader_unlock ();
6483 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6484 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6485 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6486 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6487 * artifact of how generics are encoded and should be transparent to managed code so we
6488 * need to weed out this diference when retrieving managed System.Type objects.
6490 norm_type = mono_type_normalize (type);
6491 if (norm_type != type) {
6492 res = mono_type_get_object (domain, norm_type);
6493 mono_g_hash_table_insert (domain->type_hash, type, res);
6494 mono_domain_unlock (domain);
6495 mono_loader_unlock ();
6499 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6500 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6503 if (!verify_safe_for_managed_space (type)) {
6504 mono_domain_unlock (domain);
6505 mono_loader_unlock ();
6506 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6509 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6510 gboolean is_type_done = TRUE;
6511 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6512 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6513 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6515 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6516 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6518 if (gparam->owner && gparam->owner->is_method) {
6519 MonoMethod *method = gparam->owner->owner.method;
6520 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6521 is_type_done = FALSE;
6522 } else if (gparam->owner && !gparam->owner->is_method) {
6523 MonoClass *klass = gparam->owner->owner.klass;
6524 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6525 is_type_done = FALSE;
6529 /* g_assert_not_reached (); */
6530 /* should this be considered an error condition? */
6531 if (is_type_done && !type->byref) {
6532 mono_domain_unlock (domain);
6533 mono_loader_unlock ();
6534 return mono_class_get_ref_info (klass);
6537 /* This is stored in vtables/JITted code so it has to be pinned */
6538 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6540 mono_g_hash_table_insert (domain->type_hash, type, res);
6542 if (type->type == MONO_TYPE_VOID)
6543 domain->typeof_void = (MonoObject*)res;
6545 mono_domain_unlock (domain);
6546 mono_loader_unlock ();
6551 * mono_method_get_object:
6552 * @domain: an app domain
6554 * @refclass: the reflected type (can be NULL)
6556 * Return an System.Reflection.MonoMethod object representing the method @method.
6558 MonoReflectionMethod*
6559 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6562 * We use the same C representation for methods and constructors, but the type
6563 * name in C# is different.
6565 static MonoClass *System_Reflection_MonoMethod = NULL;
6566 static MonoClass *System_Reflection_MonoCMethod = NULL;
6567 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6568 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6570 MonoReflectionMethod *ret;
6572 if (method->is_inflated) {
6573 MonoReflectionGenericMethod *gret;
6575 refclass = method->klass;
6576 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6577 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6578 if (!System_Reflection_MonoGenericCMethod)
6579 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6580 klass = System_Reflection_MonoGenericCMethod;
6582 if (!System_Reflection_MonoGenericMethod)
6583 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6584 klass = System_Reflection_MonoGenericMethod;
6586 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6587 gret->method.method = method;
6588 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6589 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6590 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6594 refclass = method->klass;
6596 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6598 if (!System_Reflection_MonoCMethod)
6599 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6600 klass = System_Reflection_MonoCMethod;
6603 if (!System_Reflection_MonoMethod)
6604 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6605 klass = System_Reflection_MonoMethod;
6607 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6608 ret->method = method;
6609 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6614 * mono_method_clear_object:
6616 * Clear the cached reflection objects for the dynamic method METHOD.
6619 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6622 g_assert (method->dynamic);
6624 klass = method->klass;
6626 clear_cached_object (domain, method, klass);
6627 klass = klass->parent;
6629 /* Added by mono_param_get_objects () */
6630 clear_cached_object (domain, &(method->signature), NULL);
6631 klass = method->klass;
6633 clear_cached_object (domain, &(method->signature), klass);
6634 klass = klass->parent;
6639 * mono_field_get_object:
6640 * @domain: an app domain
6644 * Return an System.Reflection.MonoField object representing the field @field
6647 MonoReflectionField*
6648 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6650 MonoReflectionField *res;
6651 static MonoClass *monofield_klass;
6653 CHECK_OBJECT (MonoReflectionField *, field, klass);
6654 if (!monofield_klass)
6655 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6656 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6659 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6661 if (is_field_on_inst (field)) {
6662 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6663 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6666 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6667 res->attrs = mono_field_get_flags (field);
6669 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6673 * mono_property_get_object:
6674 * @domain: an app domain
6676 * @property: a property
6678 * Return an System.Reflection.MonoProperty object representing the property @property
6681 MonoReflectionProperty*
6682 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6684 MonoReflectionProperty *res;
6685 static MonoClass *monoproperty_klass;
6687 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6688 if (!monoproperty_klass)
6689 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6690 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6692 res->property = property;
6693 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6697 * mono_event_get_object:
6698 * @domain: an app domain
6702 * Return an System.Reflection.MonoEvent object representing the event @event
6705 MonoReflectionEvent*
6706 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6708 MonoReflectionEvent *res;
6709 MonoReflectionMonoEvent *mono_event;
6710 static MonoClass *monoevent_klass;
6712 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6713 if (!monoevent_klass)
6714 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6715 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6716 mono_event->klass = klass;
6717 mono_event->event = event;
6718 res = (MonoReflectionEvent*)mono_event;
6719 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6723 * mono_get_reflection_missing_object:
6724 * @domain: Domain where the object lives
6726 * Returns the System.Reflection.Missing.Value singleton object
6727 * (of type System.Reflection.Missing).
6729 * Used as the value for ParameterInfo.DefaultValue when Optional
6733 mono_get_reflection_missing_object (MonoDomain *domain)
6736 static MonoClassField *missing_value_field = NULL;
6738 if (!missing_value_field) {
6739 MonoClass *missing_klass;
6740 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6741 mono_class_init (missing_klass);
6742 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6743 g_assert (missing_value_field);
6745 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6751 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6754 *dbnull = mono_get_dbnull_object (domain);
6759 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6761 if (!*reflection_missing)
6762 *reflection_missing = mono_get_reflection_missing_object (domain);
6763 return *reflection_missing;
6767 * mono_param_get_objects:
6768 * @domain: an app domain
6771 * Return an System.Reflection.ParameterInfo array object representing the parameters
6772 * in the method @method.
6775 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6777 static MonoClass *System_Reflection_ParameterInfo;
6778 static MonoClass *System_Reflection_ParameterInfo_array;
6780 MonoArray *res = NULL;
6781 MonoReflectionMethod *member = NULL;
6782 MonoReflectionParameter *param = NULL;
6783 char **names, **blobs = NULL;
6784 guint32 *types = NULL;
6785 MonoType *type = NULL;
6786 MonoObject *dbnull = NULL;
6787 MonoObject *missing = NULL;
6788 MonoMarshalSpec **mspecs;
6789 MonoMethodSignature *sig;
6790 MonoVTable *pinfo_vtable;
6793 if (!System_Reflection_ParameterInfo_array) {
6796 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6798 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6800 mono_memory_barrier ();
6801 System_Reflection_ParameterInfo = klass;
6804 klass = mono_array_class_get (klass, 1);
6805 mono_memory_barrier ();
6806 System_Reflection_ParameterInfo_array = klass;
6809 sig = mono_method_signature_checked (method, &error);
6810 if (!mono_error_ok (&error))
6811 mono_error_raise_exception (&error);
6813 if (!sig->param_count)
6814 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6816 /* Note: the cache is based on the address of the signature into the method
6817 * since we already cache MethodInfos with the method as keys.
6819 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6821 member = mono_method_get_object (domain, method, refclass);
6822 names = g_new (char *, sig->param_count);
6823 mono_method_get_param_names (method, (const char **) names);
6825 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6826 mono_method_get_marshal_info (method, mspecs);
6828 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6829 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6830 for (i = 0; i < sig->param_count; ++i) {
6831 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6832 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6833 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6834 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6835 param->PositionImpl = i;
6836 param->AttrsImpl = sig->params [i]->attrs;
6838 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6839 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6840 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6842 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6846 blobs = g_new0 (char *, sig->param_count);
6847 types = g_new0 (guint32, sig->param_count);
6848 get_default_param_value_blobs (method, blobs, types);
6851 /* Build MonoType for the type from the Constant Table */
6853 type = g_new0 (MonoType, 1);
6854 type->type = types [i];
6855 type->data.klass = NULL;
6856 if (types [i] == MONO_TYPE_CLASS)
6857 type->data.klass = mono_defaults.object_class;
6858 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6859 /* For enums, types [i] contains the base type */
6861 type->type = MONO_TYPE_VALUETYPE;
6862 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6864 type->data.klass = mono_class_from_mono_type (type);
6866 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6868 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6869 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6870 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6871 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6873 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6879 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6881 mono_array_setref (res, i, param);
6888 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6890 mono_metadata_free_marshal_spec (mspecs [i]);
6893 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6897 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6899 return mono_param_get_objects_internal (domain, method, NULL);
6903 * mono_method_body_get_object:
6904 * @domain: an app domain
6907 * Return an System.Reflection.MethodBody object representing the method @method.
6909 MonoReflectionMethodBody*
6910 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6912 static MonoClass *System_Reflection_MethodBody = NULL;
6913 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6914 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6915 MonoReflectionMethodBody *ret;
6916 MonoMethodHeader *header;
6918 guint32 method_rva, local_var_sig_token;
6920 unsigned char format, flags;
6923 /* for compatibility with .net */
6924 if (method->dynamic)
6925 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6927 if (!System_Reflection_MethodBody)
6928 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6929 if (!System_Reflection_LocalVariableInfo)
6930 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6931 if (!System_Reflection_ExceptionHandlingClause)
6932 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6934 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6936 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6937 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6938 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6939 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6942 image = method->klass->image;
6943 header = mono_method_get_header (method);
6945 if (!image->dynamic) {
6946 /* Obtain local vars signature token */
6947 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6948 ptr = mono_image_rva_map (image, method_rva);
6949 flags = *(const unsigned char *) ptr;
6950 format = flags & METHOD_HEADER_FORMAT_MASK;
6952 case METHOD_HEADER_TINY_FORMAT:
6953 local_var_sig_token = 0;
6955 case METHOD_HEADER_FAT_FORMAT:
6959 local_var_sig_token = read32 (ptr);
6962 g_assert_not_reached ();
6965 local_var_sig_token = 0; //FIXME
6967 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6969 ret->init_locals = header->init_locals;
6970 ret->max_stack = header->max_stack;
6971 ret->local_var_sig_token = local_var_sig_token;
6972 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6973 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6976 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6977 for (i = 0; i < header->num_locals; ++i) {
6978 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6979 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6980 info->is_pinned = header->locals [i]->pinned;
6981 info->local_index = i;
6982 mono_array_setref (ret->locals, i, info);
6986 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6987 for (i = 0; i < header->num_clauses; ++i) {
6988 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6989 MonoExceptionClause *clause = &header->clauses [i];
6991 info->flags = clause->flags;
6992 info->try_offset = clause->try_offset;
6993 info->try_length = clause->try_len;
6994 info->handler_offset = clause->handler_offset;
6995 info->handler_length = clause->handler_len;
6996 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6997 info->filter_offset = clause->data.filter_offset;
6998 else if (clause->data.catch_class)
6999 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7001 mono_array_setref (ret->clauses, i, info);
7004 mono_metadata_free_mh (header);
7005 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7010 * mono_get_dbnull_object:
7011 * @domain: Domain where the object lives
7013 * Returns the System.DBNull.Value singleton object
7015 * Used as the value for ParameterInfo.DefaultValue
7018 mono_get_dbnull_object (MonoDomain *domain)
7021 static MonoClassField *dbnull_value_field = NULL;
7023 if (!dbnull_value_field) {
7024 MonoClass *dbnull_klass;
7025 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7026 mono_class_init (dbnull_klass);
7027 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7028 g_assert (dbnull_value_field);
7030 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7036 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7038 guint32 param_index, i, lastp, crow = 0;
7039 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7042 MonoClass *klass = method->klass;
7043 MonoImage *image = klass->image;
7044 MonoMethodSignature *methodsig = mono_method_signature (method);
7046 MonoTableInfo *constt;
7047 MonoTableInfo *methodt;
7048 MonoTableInfo *paramt;
7050 if (!methodsig->param_count)
7053 mono_class_init (klass);
7055 if (klass->image->dynamic) {
7056 MonoReflectionMethodAux *aux;
7057 if (method->is_inflated)
7058 method = ((MonoMethodInflated*)method)->declaring;
7059 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7060 if (aux && aux->param_defaults) {
7061 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7062 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7067 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7068 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7069 constt = &image->tables [MONO_TABLE_CONSTANT];
7071 idx = mono_method_get_index (method) - 1;
7072 g_assert (idx != -1);
7074 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7075 if (idx + 1 < methodt->rows)
7076 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7078 lastp = paramt->rows + 1;
7080 for (i = param_index; i < lastp; ++i) {
7083 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7084 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7086 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7089 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7094 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7095 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7096 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7103 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7108 MonoType *basetype = type;
7113 klass = mono_class_from_mono_type (type);
7114 if (klass->valuetype) {
7115 object = mono_object_new (domain, klass);
7116 retval = ((gchar *) object + sizeof (MonoObject));
7117 if (klass->enumtype)
7118 basetype = mono_class_enum_basetype (klass);
7123 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7130 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7133 gboolean quoted = FALSE;
7135 memset (assembly, 0, sizeof (MonoAssemblyName));
7136 assembly->culture = "";
7137 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7144 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7155 /* Remove trailing whitespace */
7157 while (*s && g_ascii_isspace (*s))
7160 while (g_ascii_isspace (*p))
7163 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7165 assembly->major = strtoul (p, &s, 10);
7166 if (s == p || *s != '.')
7169 assembly->minor = strtoul (p, &s, 10);
7170 if (s == p || *s != '.')
7173 assembly->build = strtoul (p, &s, 10);
7174 if (s == p || *s != '.')
7177 assembly->revision = strtoul (p, &s, 10);
7181 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7183 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7184 assembly->culture = "";
7187 assembly->culture = p;
7188 while (*p && *p != ',') {
7192 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7194 if (strncmp (p, "null", 4) == 0) {
7199 while (*p && *p != ',') {
7202 len = (p - start + 1);
7203 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7204 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7205 g_strlcpy ((char*)assembly->public_key_token, start, len);
7208 while (*p && *p != ',')
7212 while (g_ascii_isspace (*p) || *p == ',') {
7226 * mono_reflection_parse_type:
7229 * Parse a type name as accepted by the GetType () method and output the info
7230 * extracted in the info structure.
7231 * the name param will be mangled, so, make a copy before passing it to this function.
7232 * The fields in info will be valid until the memory pointed to by name is valid.
7234 * See also mono_type_get_name () below.
7236 * Returns: 0 on parse error.
7239 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7240 MonoTypeNameParse *info)
7242 char *start, *p, *w, *last_point, *startn;
7243 int in_modifiers = 0;
7244 int isbyref = 0, rank = 0;
7246 start = p = w = name;
7248 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7249 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7250 info->name = info->name_space = NULL;
7251 info->nested = NULL;
7252 info->modifiers = NULL;
7253 info->type_arguments = NULL;
7255 /* last_point separates the namespace from the name */
7258 while (*p == ' ') p++, start++, w++, name++;
7263 *p = 0; /* NULL terminate the name */
7265 info->nested = g_list_append (info->nested, startn);
7266 /* we have parsed the nesting namespace + name */
7270 info->name_space = start;
7272 info->name = last_point + 1;
7274 info->name_space = (char *)"";
7302 info->name_space = start;
7304 info->name = last_point + 1;
7306 info->name_space = (char *)"";
7313 if (isbyref) /* only one level allowed by the spec */
7316 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7320 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7324 //Decide if it's an array of a generic argument list
7329 if (*p == ',' || *p == '*' || *p == ']') { //array
7336 else if (*p == '*') /* '*' means unknown lower bound */
7337 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7344 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7346 if (rank) /* generic args after array spec*/ //XXX test
7348 info->type_arguments = g_ptr_array_new ();
7350 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7351 gboolean fqname = FALSE;
7353 g_ptr_array_add (info->type_arguments, subinfo);
7360 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7363 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7364 if (fqname && (*p != ']')) {
7372 while (*p && (*p != ']'))
7380 if (g_ascii_isspace (*aname)) {
7387 !assembly_name_to_aname (&subinfo->assembly, aname))
7389 } else if (fqname && (*p == ']')) {
7411 if (g_ascii_isspace (*p)) {
7418 return 0; /* missing assembly name */
7419 if (!assembly_name_to_aname (&info->assembly, p))
7425 if (info->assembly.name)
7428 // *w = 0; /* terminate class name */
7430 if (!info->name || !*info->name)
7434 /* add other consistency checks */
7439 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7441 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7445 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7447 gboolean type_resolve = FALSE;
7449 MonoImage *rootimage = image;
7451 if (info->assembly.name) {
7452 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7453 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7455 * This could happen in the AOT compiler case when the search hook is not
7458 assembly = image->assembly;
7460 /* then we must load the assembly ourselve - see #60439 */
7461 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7465 image = assembly->image;
7466 } else if (!image) {
7467 image = mono_defaults.corlib;
7470 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7471 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7472 image = mono_defaults.corlib;
7473 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7480 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7485 gboolean bounded = FALSE;
7488 image = mono_defaults.corlib;
7491 klass = mono_class_from_name_case (image, info->name_space, info->name);
7493 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 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7508 if (strcmp (klass->name, mod->data) == 0)
7518 if (info->type_arguments) {
7519 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7520 MonoReflectionType *the_type;
7524 for (i = 0; i < info->type_arguments->len; i++) {
7525 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7527 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7528 if (!type_args [i]) {
7534 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7536 instance = mono_reflection_bind_generic_parameters (
7537 the_type, info->type_arguments->len, type_args);
7543 klass = mono_class_from_mono_type (instance);
7546 for (mod = info->modifiers; mod; mod = mod->next) {
7547 modval = GPOINTER_TO_UINT (mod->data);
7548 if (!modval) { /* byref: must be last modifier */
7549 return &klass->this_arg;
7550 } else if (modval == -1) {
7551 klass = mono_ptr_class_get (&klass->byval_arg);
7552 } else if (modval == -2) {
7554 } else { /* array rank */
7555 klass = mono_bounded_array_class_get (klass, modval, bounded);
7559 return &klass->byval_arg;
7563 * mono_reflection_get_type:
7564 * @image: a metadata context
7565 * @info: type description structure
7566 * @ignorecase: flag for case-insensitive string compares
7567 * @type_resolve: whenever type resolve was already tried
7569 * Build a MonoType from the type description in @info.
7574 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7575 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7579 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7581 MonoReflectionAssemblyBuilder *abuilder;
7585 g_assert (assembly->dynamic);
7586 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7588 /* Enumerate all modules */
7591 if (abuilder->modules) {
7592 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7593 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7594 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7600 if (!type && abuilder->loaded_modules) {
7601 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7602 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7603 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7613 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7616 MonoReflectionAssembly *assembly;
7620 if (image && image->dynamic)
7621 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7623 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7626 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7633 *type_resolve = TRUE;
7636 /* Reconstruct the type name */
7637 fullName = g_string_new ("");
7638 if (info->name_space && (info->name_space [0] != '\0'))
7639 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7641 g_string_printf (fullName, "%s", info->name);
7642 for (mod = info->nested; mod; mod = mod->next)
7643 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7645 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7647 if (assembly->assembly->dynamic)
7648 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7650 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7653 g_string_free (fullName, TRUE);
7658 mono_reflection_free_type_info (MonoTypeNameParse *info)
7660 g_list_free (info->modifiers);
7661 g_list_free (info->nested);
7663 if (info->type_arguments) {
7666 for (i = 0; i < info->type_arguments->len; i++) {
7667 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7669 mono_reflection_free_type_info (subinfo);
7670 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7674 g_ptr_array_free (info->type_arguments, TRUE);
7679 * mono_reflection_type_from_name:
7681 * @image: a metadata context (can be NULL).
7683 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7684 * it defaults to get the type from @image or, if @image is NULL or loading
7685 * from it fails, uses corlib.
7689 mono_reflection_type_from_name (char *name, MonoImage *image)
7691 MonoType *type = NULL;
7692 MonoTypeNameParse info;
7695 /* Make a copy since parse_type modifies its argument */
7696 tmp = g_strdup (name);
7698 /*g_print ("requested type %s\n", str);*/
7699 if (mono_reflection_parse_type (tmp, &info)) {
7700 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7704 mono_reflection_free_type_info (&info);
7709 * mono_reflection_get_token:
7711 * Return the metadata token of OBJ which should be an object
7712 * representing a metadata element.
7715 mono_reflection_get_token (MonoObject *obj)
7720 klass = obj->vtable->klass;
7722 if (strcmp (klass->name, "MethodBuilder") == 0) {
7723 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7725 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7726 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7727 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7729 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7730 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7731 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7733 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7734 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7735 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7736 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7737 } else if (strcmp (klass->name, "MonoType") == 0) {
7738 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7739 MonoClass *mc = mono_class_from_mono_type (type);
7740 if (!mono_class_init (mc))
7741 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7743 token = mc->type_token;
7744 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7745 strcmp (klass->name, "MonoMethod") == 0 ||
7746 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7747 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7748 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7749 if (m->method->is_inflated) {
7750 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7751 return inflated->declaring->token;
7753 token = m->method->token;
7755 } else if (strcmp (klass->name, "MonoField") == 0) {
7756 MonoReflectionField *f = (MonoReflectionField*)obj;
7758 if (is_field_on_inst (f->field)) {
7759 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7760 int field_index = f->field - dgclass->fields;
7763 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7764 obj = dgclass->field_objects [field_index];
7765 return mono_reflection_get_token (obj);
7767 token = mono_class_get_field_token (f->field);
7768 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7769 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7771 token = mono_class_get_property_token (p->property);
7772 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7773 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7775 token = mono_class_get_event_token (p->event);
7776 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7777 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7778 MonoClass *member_class = mono_object_class (p->MemberImpl);
7779 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7781 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7782 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7783 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7786 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7787 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7789 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7790 MonoException *ex = mono_get_exception_not_implemented (msg);
7792 mono_raise_exception (ex);
7799 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7803 int slen = mono_metadata_decode_value (p, &p);
7805 mono_error_init (error);
7807 n = g_memdup (p, slen + 1);
7809 t = mono_reflection_type_from_name (n, image);
7811 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7812 /* We don't free n, it's consumed by mono_error */
7813 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7819 return mono_class_from_mono_type (t);
7823 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7825 int slen, type = t->type;
7826 MonoClass *tklass = t->data.klass;
7828 mono_error_init (error);
7834 case MONO_TYPE_BOOLEAN: {
7835 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7840 case MONO_TYPE_CHAR:
7842 case MONO_TYPE_I2: {
7843 guint16 *val = g_malloc (sizeof (guint16));
7848 #if SIZEOF_VOID_P == 4
7854 case MONO_TYPE_I4: {
7855 guint32 *val = g_malloc (sizeof (guint32));
7860 #if SIZEOF_VOID_P == 8
7861 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7865 case MONO_TYPE_I8: {
7866 guint64 *val = g_malloc (sizeof (guint64));
7871 case MONO_TYPE_R8: {
7872 double *val = g_malloc (sizeof (double));
7877 case MONO_TYPE_VALUETYPE:
7878 if (t->data.klass->enumtype) {
7879 type = mono_class_enum_basetype (t->data.klass)->type;
7882 MonoClass *k = t->data.klass;
7884 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7885 guint64 *val = g_malloc (sizeof (guint64));
7891 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7894 case MONO_TYPE_STRING:
7895 if (*p == (char)0xFF) {
7899 slen = mono_metadata_decode_value (p, &p);
7901 return mono_string_new_len (mono_domain_get (), p, slen);
7902 case MONO_TYPE_CLASS: {
7905 if (*p == (char)0xFF) {
7910 slen = mono_metadata_decode_value (p, &p);
7911 n = g_memdup (p, slen + 1);
7913 t = mono_reflection_type_from_name (n, image);
7915 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7916 /* We don't free n, it's consumed by mono_error */
7917 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7922 return mono_type_get_object (mono_domain_get (), t);
7924 case MONO_TYPE_OBJECT: {
7927 MonoClass *subc = NULL;
7932 } else if (subt == 0x0E) {
7933 type = MONO_TYPE_STRING;
7935 } else if (subt == 0x1D) {
7936 MonoType simple_type = {{0}};
7940 type = MONO_TYPE_SZARRAY;
7941 if (etype == 0x50) {
7942 tklass = mono_defaults.systemtype_class;
7943 } else if (etype == 0x55) {
7944 tklass = load_cattr_enum_type (image, p, &p, error);
7945 if (!mono_error_ok (error))
7949 /* See Partition II, Appendix B3 */
7950 etype = MONO_TYPE_OBJECT;
7951 simple_type.type = etype;
7952 tklass = mono_class_from_mono_type (&simple_type);
7955 } else if (subt == 0x55) {
7958 slen = mono_metadata_decode_value (p, &p);
7959 n = g_memdup (p, slen + 1);
7961 t = mono_reflection_type_from_name (n, image);
7963 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7964 /* We don't free n, it's consumed by mono_error */
7965 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7970 subc = mono_class_from_mono_type (t);
7971 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7972 MonoType simple_type = {{0}};
7973 simple_type.type = subt;
7974 subc = mono_class_from_mono_type (&simple_type);
7976 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7978 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
7980 if (mono_error_ok (error)) {
7981 obj = mono_object_new (mono_domain_get (), subc);
7982 g_assert (!subc->has_references);
7983 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7989 case MONO_TYPE_SZARRAY: {
7991 guint32 i, alen, basetype;
7994 if (alen == 0xffffffff) {
7998 arr = mono_array_new (mono_domain_get(), tklass, alen);
7999 basetype = tklass->byval_arg.type;
8000 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8001 basetype = mono_class_enum_basetype (tklass)->type;
8006 case MONO_TYPE_BOOLEAN:
8007 for (i = 0; i < alen; i++) {
8008 MonoBoolean val = *p++;
8009 mono_array_set (arr, MonoBoolean, i, val);
8012 case MONO_TYPE_CHAR:
8015 for (i = 0; i < alen; i++) {
8016 guint16 val = read16 (p);
8017 mono_array_set (arr, guint16, i, val);
8024 for (i = 0; i < alen; i++) {
8025 guint32 val = read32 (p);
8026 mono_array_set (arr, guint32, i, val);
8031 for (i = 0; i < alen; i++) {
8034 mono_array_set (arr, double, i, val);
8040 for (i = 0; i < alen; i++) {
8041 guint64 val = read64 (p);
8042 mono_array_set (arr, guint64, i, val);
8046 case MONO_TYPE_CLASS:
8047 case MONO_TYPE_OBJECT:
8048 case MONO_TYPE_STRING:
8049 case MONO_TYPE_SZARRAY:
8050 for (i = 0; i < alen; i++) {
8051 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8052 if (!mono_error_ok (error))
8054 mono_array_setref (arr, i, item);
8058 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8064 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8070 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8072 static MonoClass *klass;
8073 static MonoMethod *ctor;
8075 void *params [2], *unboxed;
8078 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8080 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8082 params [0] = mono_type_get_object (mono_domain_get (), t);
8084 retval = mono_object_new (mono_domain_get (), klass);
8085 unboxed = mono_object_unbox (retval);
8086 mono_runtime_invoke (ctor, unboxed, params, NULL);
8092 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8094 static MonoClass *klass;
8095 static MonoMethod *ctor;
8097 void *unboxed, *params [2];
8100 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8102 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8105 params [1] = typedarg;
8106 retval = mono_object_new (mono_domain_get (), klass);
8107 unboxed = mono_object_unbox (retval);
8108 mono_runtime_invoke (ctor, unboxed, params, NULL);
8114 type_is_reference (MonoType *type)
8116 switch (type->type) {
8117 case MONO_TYPE_BOOLEAN:
8118 case MONO_TYPE_CHAR:
8131 case MONO_TYPE_VALUETYPE:
8139 free_param_data (MonoMethodSignature *sig, void **params) {
8141 for (i = 0; i < sig->param_count; ++i) {
8142 if (!type_is_reference (sig->params [i]))
8143 g_free (params [i]);
8148 * Find the field index in the metadata FieldDef table.
8151 find_field_index (MonoClass *klass, MonoClassField *field) {
8154 for (i = 0; i < klass->field.count; ++i) {
8155 if (field == &klass->fields [i])
8156 return klass->field.first + 1 + i;
8162 * Find the property index in the metadata Property table.
8165 find_property_index (MonoClass *klass, MonoProperty *property) {
8168 for (i = 0; i < klass->ext->property.count; ++i) {
8169 if (property == &klass->ext->properties [i])
8170 return klass->ext->property.first + 1 + i;
8176 * Find the event index in the metadata Event table.
8179 find_event_index (MonoClass *klass, MonoEvent *event) {
8182 for (i = 0; i < klass->ext->event.count; ++i) {
8183 if (event == &klass->ext->events [i])
8184 return klass->ext->event.first + 1 + i;
8190 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8192 const char *p = (const char*)data;
8194 guint32 i, j, num_named;
8196 void *params_buf [32];
8197 void **params = NULL;
8198 MonoMethodSignature *sig;
8199 MonoObject *exc = NULL;
8201 mono_error_init (error);
8203 mono_class_init (method->klass);
8205 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8206 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8211 attr = mono_object_new (mono_domain_get (), method->klass);
8212 mono_runtime_invoke (method, attr, NULL, NULL);
8216 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8219 /*g_print ("got attr %s\n", method->klass->name);*/
8221 sig = mono_method_signature (method);
8222 if (sig->param_count < 32) {
8223 params = params_buf;
8224 memset (params, 0, sizeof (void*) * sig->param_count);
8226 /* Allocate using GC so it gets GC tracking */
8227 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8232 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8233 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8234 if (!mono_error_ok (error))
8239 attr = mono_object_new (mono_domain_get (), method->klass);
8241 mono_runtime_invoke (method, attr, params, &exc);
8244 num_named = read16 (named);
8246 for (j = 0; j < num_named; j++) {
8248 char *name, named_type, data_type;
8249 named_type = *named++;
8250 data_type = *named++; /* type of data */
8251 if (data_type == MONO_TYPE_SZARRAY)
8252 data_type = *named++;
8253 if (data_type == MONO_TYPE_ENUM) {
8256 type_len = mono_metadata_decode_blob_size (named, &named);
8257 type_name = g_malloc (type_len + 1);
8258 memcpy (type_name, named, type_len);
8259 type_name [type_len] = 0;
8261 /* FIXME: lookup the type and check type consistency */
8264 name_len = mono_metadata_decode_blob_size (named, &named);
8265 name = g_malloc (name_len + 1);
8266 memcpy (name, named, name_len);
8267 name [name_len] = 0;
8269 if (named_type == 0x53) {
8270 MonoClassField *field;
8273 /* how this fail is a blackbox */
8274 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8276 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8281 val = load_cattr_value (image, field->type, named, &named, error);
8282 if (!mono_error_ok (error)) {
8284 if (!type_is_reference (field->type))
8289 mono_field_set_value (attr, field, val);
8290 if (!type_is_reference (field->type))
8292 } else if (named_type == 0x54) {
8295 MonoType *prop_type;
8297 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8300 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8306 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8311 /* can we have more that 1 arg in a custom attr named property? */
8312 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8313 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8315 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8316 if (!mono_error_ok (error)) {
8318 if (!type_is_reference (prop_type))
8319 g_free (pparams [0]);
8324 mono_property_set_value (prop, attr, pparams, NULL);
8325 if (!type_is_reference (prop_type))
8326 g_free (pparams [0]);
8331 free_param_data (method->signature, params);
8332 if (params != params_buf)
8333 mono_gc_free_fixed (params);
8338 free_param_data (method->signature, params);
8339 if (params != params_buf)
8340 mono_gc_free_fixed (params);
8342 mono_raise_exception ((MonoException*)exc);
8347 * mono_reflection_create_custom_attr_data_args:
8349 * Create an array of typed and named arguments from the cattr blob given by DATA.
8350 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8351 * NAMED_ARG_INFO will contain information about the named arguments.
8354 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)
8356 MonoArray *typedargs, *namedargs;
8357 MonoClass *attrklass;
8359 const char *p = (const char*)data;
8361 guint32 i, j, num_named;
8362 CattrNamedArg *arginfo = NULL;
8366 *named_arg_info = NULL;
8368 mono_error_init (error);
8370 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8371 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8375 mono_class_init (method->klass);
8377 domain = mono_domain_get ();
8379 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8382 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8386 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8390 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8391 if (!mono_error_ok (error)) {
8392 if (!type_is_reference (mono_method_signature (method)->params [i]))
8397 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8398 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8399 mono_array_setref (typedargs, i, obj);
8401 if (!type_is_reference (mono_method_signature (method)->params [i]))
8406 num_named = read16 (named);
8407 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8409 attrklass = method->klass;
8411 arginfo = g_new0 (CattrNamedArg, num_named);
8412 *named_arg_info = arginfo;
8414 for (j = 0; j < num_named; j++) {
8416 char *name, named_type, data_type;
8417 named_type = *named++;
8418 data_type = *named++; /* type of data */
8419 if (data_type == MONO_TYPE_SZARRAY)
8420 data_type = *named++;
8421 if (data_type == MONO_TYPE_ENUM) {
8424 type_len = mono_metadata_decode_blob_size (named, &named);
8425 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8428 type_name = g_malloc (type_len + 1);
8429 memcpy (type_name, named, type_len);
8430 type_name [type_len] = 0;
8432 /* FIXME: lookup the type and check type consistency */
8435 name_len = mono_metadata_decode_blob_size (named, &named);
8436 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8438 name = g_malloc (name_len + 1);
8439 memcpy (name, named, name_len);
8440 name [name_len] = 0;
8442 if (named_type == 0x53) {
8444 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8452 arginfo [j].type = field->type;
8453 arginfo [j].field = field;
8455 val = load_cattr_value (image, field->type, named, &named, error);
8456 if (!mono_error_ok (error)) {
8457 if (!type_is_reference (field->type))
8463 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8464 mono_array_setref (namedargs, j, obj);
8465 if (!type_is_reference (field->type))
8467 } else if (named_type == 0x54) {
8469 MonoType *prop_type;
8470 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8473 if (!prop || !prop->set) {
8478 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8479 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8481 arginfo [j].type = prop_type;
8482 arginfo [j].prop = prop;
8484 val = load_cattr_value (image, prop_type, named, &named, error);
8485 if (!mono_error_ok (error)) {
8486 if (!type_is_reference (prop_type))
8492 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8493 mono_array_setref (namedargs, j, obj);
8494 if (!type_is_reference (prop_type))
8500 *typed_args = typedargs;
8501 *named_args = namedargs;
8504 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8506 *named_arg_info = NULL;
8510 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8513 MonoArray *typedargs, *namedargs;
8516 CattrNamedArg *arginfo = NULL;
8526 image = assembly->assembly->image;
8527 method = ref_method->method;
8528 domain = mono_object_domain (ref_method);
8530 if (!mono_class_init (method->klass))
8531 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8533 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8534 if (!mono_error_ok (&error))
8535 mono_error_raise_exception (&error);
8536 if (mono_loader_get_last_error ())
8537 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8539 if (!typedargs || !namedargs) {
8544 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8545 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8546 MonoObject *typedarg;
8548 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8549 mono_array_setref (typedargs, i, typedarg);
8552 for (i = 0; i < mono_array_length (namedargs); ++i) {
8553 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8554 MonoObject *typedarg, *namedarg, *minfo;
8556 if (arginfo [i].prop)
8557 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8559 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8561 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8562 namedarg = create_cattr_named_arg (minfo, typedarg);
8564 mono_array_setref (namedargs, i, namedarg);
8567 *ctor_args = typedargs;
8568 *named_args = namedargs;
8573 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8575 static MonoMethod *ctor;
8580 g_assert (image->assembly);
8583 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8585 domain = mono_domain_get ();
8586 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8587 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8588 params [1] = mono_assembly_get_object (domain, image->assembly);
8589 params [2] = (gpointer)&cattr->data;
8590 params [3] = &cattr->data_size;
8591 mono_runtime_invoke (ctor, attr, params, NULL);
8596 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8602 mono_error_init (error);
8605 for (i = 0; i < cinfo->num_attrs; ++i) {
8606 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8610 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8612 for (i = 0; i < cinfo->num_attrs; ++i) {
8613 if (!cinfo->attrs [i].ctor)
8614 /* The cattr type is not finished yet */
8615 /* We should include the type name but cinfo doesn't contain it */
8616 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8617 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8618 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8619 if (!mono_error_ok (error))
8621 mono_array_setref (result, n, attr);
8629 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8632 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8633 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8639 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8645 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8646 for (i = 0; i < cinfo->num_attrs; ++i) {
8647 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8648 mono_array_setref (result, i, attr);
8654 * mono_custom_attrs_from_index:
8656 * Returns: NULL if no attributes are found or if a loading error occurs.
8659 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8661 guint32 mtoken, i, len;
8662 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8664 MonoCustomAttrInfo *ainfo;
8665 GList *tmp, *list = NULL;
8668 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8670 i = mono_metadata_custom_attrs_from_index (image, idx);
8674 while (i < ca->rows) {
8675 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8677 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8680 len = g_list_length (list);
8683 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8684 ainfo->num_attrs = len;
8685 ainfo->image = image;
8686 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8687 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8688 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8689 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8690 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8691 mtoken |= MONO_TOKEN_METHOD_DEF;
8693 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8694 mtoken |= MONO_TOKEN_MEMBER_REF;
8697 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8700 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8701 if (!ainfo->attrs [i].ctor) {
8702 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8708 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8709 /*FIXME raising an exception here doesn't make any sense*/
8710 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8715 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8716 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8717 ainfo->attrs [i].data = (guchar*)data;
8725 mono_custom_attrs_from_method (MonoMethod *method)
8730 * An instantiated method has the same cattrs as the generic method definition.
8732 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8733 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8735 if (method->is_inflated)
8736 method = ((MonoMethodInflated *) method)->declaring;
8738 if (method->dynamic || method->klass->image->dynamic)
8739 return lookup_custom_attr (method->klass->image, method);
8742 /* Synthetic methods */
8745 idx = mono_method_get_index (method);
8746 idx <<= MONO_CUSTOM_ATTR_BITS;
8747 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8748 return mono_custom_attrs_from_index (method->klass->image, idx);
8752 mono_custom_attrs_from_class (MonoClass *klass)
8756 if (klass->generic_class)
8757 klass = klass->generic_class->container_class;
8759 if (klass->image->dynamic)
8760 return lookup_custom_attr (klass->image, klass);
8762 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8763 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8764 idx <<= MONO_CUSTOM_ATTR_BITS;
8765 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8767 idx = mono_metadata_token_index (klass->type_token);
8768 idx <<= MONO_CUSTOM_ATTR_BITS;
8769 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8771 return mono_custom_attrs_from_index (klass->image, idx);
8775 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8779 if (assembly->image->dynamic)
8780 return lookup_custom_attr (assembly->image, assembly);
8781 idx = 1; /* there is only one assembly */
8782 idx <<= MONO_CUSTOM_ATTR_BITS;
8783 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8784 return mono_custom_attrs_from_index (assembly->image, idx);
8787 static MonoCustomAttrInfo*
8788 mono_custom_attrs_from_module (MonoImage *image)
8793 return lookup_custom_attr (image, image);
8794 idx = 1; /* there is only one module */
8795 idx <<= MONO_CUSTOM_ATTR_BITS;
8796 idx |= MONO_CUSTOM_ATTR_MODULE;
8797 return mono_custom_attrs_from_index (image, idx);
8801 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8805 if (klass->image->dynamic) {
8806 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8807 return lookup_custom_attr (klass->image, property);
8809 idx = find_property_index (klass, property);
8810 idx <<= MONO_CUSTOM_ATTR_BITS;
8811 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8812 return mono_custom_attrs_from_index (klass->image, idx);
8816 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8820 if (klass->image->dynamic) {
8821 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8822 return lookup_custom_attr (klass->image, event);
8824 idx = find_event_index (klass, event);
8825 idx <<= MONO_CUSTOM_ATTR_BITS;
8826 idx |= MONO_CUSTOM_ATTR_EVENT;
8827 return mono_custom_attrs_from_index (klass->image, idx);
8831 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8834 if (klass->image->dynamic) {
8835 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8836 return lookup_custom_attr (klass->image, field);
8838 idx = find_field_index (klass, field);
8839 idx <<= MONO_CUSTOM_ATTR_BITS;
8840 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8841 return mono_custom_attrs_from_index (klass->image, idx);
8845 * mono_custom_attrs_from_param:
8846 * @method: handle to the method that we want to retrieve custom parameter information from
8847 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8849 * The result must be released with mono_custom_attrs_free().
8851 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8854 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8857 guint32 i, idx, method_index;
8858 guint32 param_list, param_last, param_pos, found;
8860 MonoReflectionMethodAux *aux;
8863 * An instantiated method has the same cattrs as the generic method definition.
8865 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8866 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8868 if (method->is_inflated)
8869 method = ((MonoMethodInflated *) method)->declaring;
8871 if (method->klass->image->dynamic) {
8872 MonoCustomAttrInfo *res, *ainfo;
8875 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8876 if (!aux || !aux->param_cattr)
8879 /* Need to copy since it will be freed later */
8880 ainfo = aux->param_cattr [param];
8883 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8884 res = g_malloc0 (size);
8885 memcpy (res, ainfo, size);
8889 image = method->klass->image;
8890 method_index = mono_method_get_index (method);
8893 ca = &image->tables [MONO_TABLE_METHOD];
8895 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8896 if (method_index == ca->rows) {
8897 ca = &image->tables [MONO_TABLE_PARAM];
8898 param_last = ca->rows + 1;
8900 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8901 ca = &image->tables [MONO_TABLE_PARAM];
8904 for (i = param_list; i < param_last; ++i) {
8905 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8906 if (param_pos == param) {
8914 idx <<= MONO_CUSTOM_ATTR_BITS;
8915 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8916 return mono_custom_attrs_from_index (image, idx);
8920 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8924 for (i = 0; i < ainfo->num_attrs; ++i) {
8925 klass = ainfo->attrs [i].ctor->klass;
8926 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8933 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8936 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
8937 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8942 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
8948 mono_error_init (error);
8951 for (i = 0; i < ainfo->num_attrs; ++i) {
8952 klass = ainfo->attrs [i].ctor->klass;
8953 if (mono_class_has_parent (klass, attr_klass)) {
8958 if (attr_index == -1)
8961 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
8962 if (!mono_error_ok (error))
8964 return mono_array_get (attrs, MonoObject*, attr_index);
8968 * mono_reflection_get_custom_attrs_info:
8969 * @obj: a reflection object handle
8971 * Return the custom attribute info for attributes defined for the
8972 * reflection handle @obj. The objects.
8974 * FIXME this function leaks like a sieve for SRE objects.
8977 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8980 MonoCustomAttrInfo *cinfo = NULL;
8982 klass = obj->vtable->klass;
8983 if (klass == mono_defaults.monotype_class) {
8984 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8985 klass = mono_class_from_mono_type (type);
8986 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8987 cinfo = mono_custom_attrs_from_class (klass);
8988 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8989 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8990 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8991 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8992 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8993 cinfo = mono_custom_attrs_from_module (module->image);
8994 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8995 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8996 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8997 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8998 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8999 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9000 } else if (strcmp ("MonoField", klass->name) == 0) {
9001 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9002 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9003 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9004 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9005 cinfo = mono_custom_attrs_from_method (rmethod->method);
9006 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9007 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9008 cinfo = mono_custom_attrs_from_method (rmethod->method);
9009 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9010 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9011 MonoClass *member_class = mono_object_class (param->MemberImpl);
9012 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9013 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9014 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9015 } else if (is_sr_mono_property (member_class)) {
9016 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9018 if (!(method = prop->property->get))
9019 method = prop->property->set;
9022 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9024 #ifndef DISABLE_REFLECTION_EMIT
9025 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9026 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9027 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9028 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9029 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9030 MonoMethod *method = NULL;
9031 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9032 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9033 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9034 method = ((MonoReflectionMethod *)c->cb)->method;
9036 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));
9038 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9042 char *type_name = mono_type_get_full_name (member_class);
9043 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9044 MonoException *ex = mono_get_exception_not_supported (msg);
9047 mono_raise_exception (ex);
9049 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9050 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9051 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9052 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9053 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9054 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9055 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9056 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9057 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9058 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9059 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9060 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9061 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9062 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9063 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9064 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9065 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9066 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9067 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9068 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9069 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9070 } else { /* handle other types here... */
9071 g_error ("get custom attrs not yet supported for %s", klass->name);
9078 * mono_reflection_get_custom_attrs_by_type:
9079 * @obj: a reflection object handle
9081 * Return an array with all the custom attributes defined of the
9082 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9083 * of that type are returned. The objects are fully build. Return NULL if a loading error
9087 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9090 MonoCustomAttrInfo *cinfo;
9092 mono_error_init (error);
9094 cinfo = mono_reflection_get_custom_attrs_info (obj);
9096 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9098 mono_custom_attrs_free (cinfo);
9100 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9101 if (mono_loader_get_last_error ())
9103 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9110 * mono_reflection_get_custom_attrs:
9111 * @obj: a reflection object handle
9113 * Return an array with all the custom attributes defined of the
9114 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9118 mono_reflection_get_custom_attrs (MonoObject *obj)
9122 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9126 * mono_reflection_get_custom_attrs_data:
9127 * @obj: a reflection obj handle
9129 * Returns an array of System.Reflection.CustomAttributeData,
9130 * which include information about attributes reflected on
9131 * types loaded using the Reflection Only methods
9134 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9137 MonoCustomAttrInfo *cinfo;
9139 cinfo = mono_reflection_get_custom_attrs_info (obj);
9141 result = mono_custom_attrs_data_construct (cinfo);
9143 mono_custom_attrs_free (cinfo);
9145 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9150 static MonoReflectionType*
9151 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9153 static MonoMethod *method_get_underlying_system_type = NULL;
9154 MonoMethod *usertype_method;
9156 if (!method_get_underlying_system_type)
9157 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9158 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9159 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9164 is_corlib_type (MonoClass *class)
9166 return class->image == mono_defaults.corlib;
9169 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9170 static MonoClass *cached_class; \
9172 return cached_class == _class; \
9173 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9174 cached_class = _class; \
9181 #ifndef DISABLE_REFLECTION_EMIT
9183 is_sre_array (MonoClass *class)
9185 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9189 is_sre_byref (MonoClass *class)
9191 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9195 is_sre_pointer (MonoClass *class)
9197 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9201 is_sre_generic_instance (MonoClass *class)
9203 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9207 is_sre_type_builder (MonoClass *class)
9209 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9213 is_sre_method_builder (MonoClass *class)
9215 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9219 is_sre_ctor_builder (MonoClass *class)
9221 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9225 is_sre_field_builder (MonoClass *class)
9227 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9231 is_sre_method_on_tb_inst (MonoClass *class)
9233 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9237 is_sre_ctor_on_tb_inst (MonoClass *class)
9239 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9243 mono_reflection_type_get_handle (MonoReflectionType* ref)
9251 if (is_usertype (ref)) {
9252 ref = mono_reflection_type_get_underlying_system_type (ref);
9253 if (ref == NULL || is_usertype (ref))
9259 class = mono_object_class (ref);
9261 if (is_sre_array (class)) {
9263 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9264 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9266 if (sre_array->rank == 0) //single dimentional array
9267 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9269 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9270 sre_array->type.type = res;
9272 } else if (is_sre_byref (class)) {
9274 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9275 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9277 res = &mono_class_from_mono_type (base)->this_arg;
9278 sre_byref->type.type = res;
9280 } else if (is_sre_pointer (class)) {
9282 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9283 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9285 res = &mono_ptr_class_get (base)->byval_arg;
9286 sre_pointer->type.type = res;
9288 } else if (is_sre_generic_instance (class)) {
9289 MonoType *res, **types;
9290 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9293 count = mono_array_length (gclass->type_arguments);
9294 types = g_new0 (MonoType*, count);
9295 for (i = 0; i < count; ++i) {
9296 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9297 types [i] = mono_reflection_type_get_handle (t);
9304 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9307 gclass->type.type = res;
9311 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9318 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9320 mono_reflection_type_get_handle (type);
9324 mono_reflection_register_with_runtime (MonoReflectionType *type)
9326 MonoType *res = mono_reflection_type_get_handle (type);
9327 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9331 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9333 class = mono_class_from_mono_type (res);
9335 mono_loader_lock (); /*same locking as mono_type_get_object*/
9336 mono_domain_lock (domain);
9338 if (!class->image->dynamic) {
9339 mono_class_setup_supertypes (class);
9341 if (!domain->type_hash)
9342 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9343 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9344 mono_g_hash_table_insert (domain->type_hash, res, type);
9346 mono_domain_unlock (domain);
9347 mono_loader_unlock ();
9351 * LOCKING: Assumes the loader lock is held.
9353 static MonoMethodSignature*
9354 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9355 MonoMethodSignature *sig;
9358 count = parameters? mono_array_length (parameters): 0;
9360 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9361 sig->param_count = count;
9362 sig->sentinelpos = -1; /* FIXME */
9363 for (i = 0; i < count; ++i)
9364 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9369 * LOCKING: Assumes the loader lock is held.
9371 static MonoMethodSignature*
9372 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9373 MonoMethodSignature *sig;
9375 sig = parameters_to_signature (image, ctor->parameters);
9376 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9377 sig->ret = &mono_defaults.void_class->byval_arg;
9382 * LOCKING: Assumes the loader lock is held.
9384 static MonoMethodSignature*
9385 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9386 MonoMethodSignature *sig;
9388 sig = parameters_to_signature (image, method->parameters);
9389 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9390 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9391 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9395 static MonoMethodSignature*
9396 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9397 MonoMethodSignature *sig;
9399 sig = parameters_to_signature (NULL, method->parameters);
9400 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9401 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9402 sig->generic_param_count = 0;
9407 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9409 MonoClass *klass = mono_object_class (prop);
9410 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9411 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9412 *name = mono_string_to_utf8 (pb->name);
9413 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9415 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9416 *name = g_strdup (p->property->name);
9417 if (p->property->get)
9418 *type = mono_method_signature (p->property->get)->ret;
9420 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9425 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9427 MonoClass *klass = mono_object_class (field);
9428 if (strcmp (klass->name, "FieldBuilder") == 0) {
9429 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9430 *name = mono_string_to_utf8 (fb->name);
9431 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9433 MonoReflectionField *f = (MonoReflectionField *)field;
9434 *name = g_strdup (mono_field_get_name (f->field));
9435 *type = f->field->type;
9439 #else /* DISABLE_REFLECTION_EMIT */
9442 mono_reflection_register_with_runtime (MonoReflectionType *type)
9448 is_sre_type_builder (MonoClass *class)
9454 is_sre_generic_instance (MonoClass *class)
9460 init_type_builder_generics (MonoObject *type)
9464 #endif /* !DISABLE_REFLECTION_EMIT */
9468 is_sr_mono_field (MonoClass *class)
9470 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9474 is_sr_mono_property (MonoClass *class)
9476 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9480 is_sr_mono_method (MonoClass *class)
9482 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9486 is_sr_mono_cmethod (MonoClass *class)
9488 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9492 is_sr_mono_generic_method (MonoClass *class)
9494 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9498 is_sr_mono_generic_cmethod (MonoClass *class)
9500 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9504 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9506 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9510 is_usertype (MonoReflectionType *ref)
9512 MonoClass *class = mono_object_class (ref);
9513 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9516 static MonoReflectionType*
9517 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9519 if (!type || type->type)
9522 if (is_usertype (type)) {
9523 type = mono_reflection_type_get_underlying_system_type (type);
9524 if (is_usertype (type))
9525 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9531 * Encode a value in a custom attribute stream of bytes.
9532 * The value to encode is either supplied as an object in argument val
9533 * (valuetypes are boxed), or as a pointer to the data in the
9535 * @type represents the type of the value
9536 * @buffer is the start of the buffer
9537 * @p the current position in the buffer
9538 * @buflen contains the size of the buffer and is used to return the new buffer size
9539 * if this needs to be realloced.
9540 * @retbuffer and @retp return the start and the position of the buffer
9543 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9545 MonoTypeEnum simple_type;
9547 if ((p-buffer) + 10 >= *buflen) {
9550 newbuf = g_realloc (buffer, *buflen);
9551 p = newbuf + (p-buffer);
9555 argval = ((char*)arg + sizeof (MonoObject));
9556 simple_type = type->type;
9558 switch (simple_type) {
9559 case MONO_TYPE_BOOLEAN:
9564 case MONO_TYPE_CHAR:
9567 swap_with_size (p, argval, 2, 1);
9573 swap_with_size (p, argval, 4, 1);
9577 swap_with_size (p, argval, 8, 1);
9582 swap_with_size (p, argval, 8, 1);
9585 case MONO_TYPE_VALUETYPE:
9586 if (type->data.klass->enumtype) {
9587 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9590 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9593 case MONO_TYPE_STRING: {
9600 str = mono_string_to_utf8 ((MonoString*)arg);
9601 slen = strlen (str);
9602 if ((p-buffer) + 10 + slen >= *buflen) {
9606 newbuf = g_realloc (buffer, *buflen);
9607 p = newbuf + (p-buffer);
9610 mono_metadata_encode_value (slen, p, &p);
9611 memcpy (p, str, slen);
9616 case MONO_TYPE_CLASS: {
9624 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9625 slen = strlen (str);
9626 if ((p-buffer) + 10 + slen >= *buflen) {
9630 newbuf = g_realloc (buffer, *buflen);
9631 p = newbuf + (p-buffer);
9634 mono_metadata_encode_value (slen, p, &p);
9635 memcpy (p, str, slen);
9640 case MONO_TYPE_SZARRAY: {
9642 MonoClass *eclass, *arg_eclass;
9645 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9648 len = mono_array_length ((MonoArray*)arg);
9650 *p++ = (len >> 8) & 0xff;
9651 *p++ = (len >> 16) & 0xff;
9652 *p++ = (len >> 24) & 0xff;
9654 *retbuffer = buffer;
9655 eclass = type->data.klass;
9656 arg_eclass = mono_object_class (arg)->element_class;
9659 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9660 eclass = mono_defaults.object_class;
9662 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9663 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9664 int elsize = mono_class_array_element_size (arg_eclass);
9665 for (i = 0; i < len; ++i) {
9666 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9669 } else if (eclass->valuetype && arg_eclass->valuetype) {
9670 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9671 int elsize = mono_class_array_element_size (eclass);
9672 for (i = 0; i < len; ++i) {
9673 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9677 for (i = 0; i < len; ++i) {
9678 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9683 case MONO_TYPE_OBJECT: {
9689 * The parameter type is 'object' but the type of the actual
9690 * argument is not. So we have to add type information to the blob
9691 * too. This is completely undocumented in the spec.
9695 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9700 klass = mono_object_class (arg);
9702 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9705 } else if (klass->enumtype) {
9707 } else if (klass == mono_defaults.string_class) {
9708 simple_type = MONO_TYPE_STRING;
9711 } else if (klass->rank == 1) {
9713 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9714 /* See Partition II, Appendix B3 */
9717 *p++ = klass->element_class->byval_arg.type;
9718 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9720 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9721 *p++ = simple_type = klass->byval_arg.type;
9724 g_error ("unhandled type in custom attr");
9726 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9727 slen = strlen (str);
9728 if ((p-buffer) + 10 + slen >= *buflen) {
9732 newbuf = g_realloc (buffer, *buflen);
9733 p = newbuf + (p-buffer);
9736 mono_metadata_encode_value (slen, p, &p);
9737 memcpy (p, str, slen);
9740 simple_type = mono_class_enum_basetype (klass)->type;
9744 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9747 *retbuffer = buffer;
9751 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9753 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9754 char *str = type_get_qualified_name (type, NULL);
9755 int slen = strlen (str);
9759 * This seems to be optional...
9762 mono_metadata_encode_value (slen, p, &p);
9763 memcpy (p, str, slen);
9766 } else if (type->type == MONO_TYPE_OBJECT) {
9768 } else if (type->type == MONO_TYPE_CLASS) {
9769 /* it should be a type: encode_cattr_value () has the check */
9772 mono_metadata_encode_value (type->type, p, &p);
9773 if (type->type == MONO_TYPE_SZARRAY)
9774 /* See the examples in Partition VI, Annex B */
9775 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9781 #ifndef DISABLE_REFLECTION_EMIT
9783 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9786 /* Preallocate a large enough buffer */
9787 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9788 char *str = type_get_qualified_name (type, NULL);
9791 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9792 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9798 len += strlen (name);
9800 if ((p-buffer) + 20 + len >= *buflen) {
9804 newbuf = g_realloc (buffer, *buflen);
9805 p = newbuf + (p-buffer);
9809 encode_field_or_prop_type (type, p, &p);
9811 len = strlen (name);
9812 mono_metadata_encode_value (len, p, &p);
9813 memcpy (p, name, len);
9815 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9817 *retbuffer = buffer;
9821 * mono_reflection_get_custom_attrs_blob:
9822 * @ctor: custom attribute constructor
9823 * @ctorArgs: arguments o the constructor
9829 * Creates the blob of data that needs to be saved in the metadata and that represents
9830 * the custom attributed described by @ctor, @ctorArgs etc.
9831 * Returns: a Byte array representing the blob of data.
9834 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9837 MonoMethodSignature *sig;
9842 MONO_ARCH_SAVE_REGS;
9844 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9845 /* sig is freed later so allocate it in the heap */
9846 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9848 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9851 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9853 p = buffer = g_malloc (buflen);
9854 /* write the prolog */
9857 for (i = 0; i < sig->param_count; ++i) {
9858 arg = mono_array_get (ctorArgs, MonoObject*, i);
9859 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9863 i += mono_array_length (properties);
9865 i += mono_array_length (fields);
9867 *p++ = (i >> 8) & 0xff;
9870 for (i = 0; i < mono_array_length (properties); ++i) {
9874 prop = mono_array_get (properties, gpointer, i);
9875 get_prop_name_and_type (prop, &pname, &ptype);
9876 *p++ = 0x54; /* PROPERTY signature */
9877 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9884 for (i = 0; i < mono_array_length (fields); ++i) {
9888 field = mono_array_get (fields, gpointer, i);
9889 get_field_name_and_type (field, &fname, &ftype);
9890 *p++ = 0x53; /* FIELD signature */
9891 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9896 g_assert (p - buffer <= buflen);
9897 buflen = p - buffer;
9898 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9899 p = mono_array_addr (result, char, 0);
9900 memcpy (p, buffer, buflen);
9902 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9908 * mono_reflection_setup_internal_class:
9909 * @tb: a TypeBuilder object
9911 * Creates a MonoClass that represents the TypeBuilder.
9912 * This is a trick that lets us simplify a lot of reflection code
9913 * (and will allow us to support Build and Run assemblies easier).
9916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9919 MonoClass *klass, *parent;
9921 MONO_ARCH_SAVE_REGS;
9923 RESOLVE_TYPE (tb->parent);
9925 mono_loader_lock ();
9928 /* check so we can compile corlib correctly */
9929 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9930 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9931 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9933 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9939 /* the type has already being created: it means we just have to change the parent */
9940 if (tb->type.type) {
9941 klass = mono_class_from_mono_type (tb->type.type);
9942 klass->parent = NULL;
9943 /* fool mono_class_setup_parent */
9944 klass->supertypes = NULL;
9945 mono_class_setup_parent (klass, parent);
9946 mono_class_setup_mono_type (klass);
9947 mono_loader_unlock ();
9951 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9953 klass->image = &tb->module->dynamic_image->image;
9955 klass->inited = 1; /* we lie to the runtime */
9956 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9957 if (!mono_error_ok (&error))
9959 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9960 if (!mono_error_ok (&error))
9962 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9963 klass->flags = tb->attrs;
9965 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9967 klass->element_class = klass;
9969 if (mono_class_get_ref_info (klass) == NULL) {
9971 mono_class_set_ref_info (klass, tb);
9973 /* Put into cache so mono_class_get () will find it.
9974 Skip nested types as those should not be available on the global scope. */
9975 if (!tb->nesting_type)
9976 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9979 We must register all types as we cannot rely on the name_cache hashtable since we find the class
9980 by performing a mono_class_get which does the full resolution.
9982 Working around this semantics would require us to write a lot of code for no clear advantage.
9984 mono_image_append_class_to_reflection_info_set (klass);
9986 g_assert (mono_class_get_ref_info (klass) == tb);
9989 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9990 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9992 if (parent != NULL) {
9993 mono_class_setup_parent (klass, parent);
9994 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9995 const char *old_n = klass->name;
9996 /* trick to get relative numbering right when compiling corlib */
9997 klass->name = "BuildingObject";
9998 mono_class_setup_parent (klass, mono_defaults.object_class);
9999 klass->name = old_n;
10002 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10003 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10004 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10005 klass->instance_size = sizeof (MonoObject);
10006 klass->size_inited = 1;
10007 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10010 mono_class_setup_mono_type (klass);
10012 mono_class_setup_supertypes (klass);
10015 * FIXME: handle interfaces.
10018 tb->type.type = &klass->byval_arg;
10020 if (tb->nesting_type) {
10021 g_assert (tb->nesting_type->type);
10022 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10025 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10027 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10029 mono_loader_unlock ();
10033 mono_loader_unlock ();
10034 mono_error_raise_exception (&error);
10038 * mono_reflection_setup_generic_class:
10039 * @tb: a TypeBuilder object
10041 * Setup the generic class before adding the first generic parameter.
10044 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10049 * mono_reflection_create_generic_class:
10050 * @tb: a TypeBuilder object
10052 * Creates the generic class after all generic parameters have been added.
10055 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10060 MONO_ARCH_SAVE_REGS;
10062 klass = mono_class_from_mono_type (tb->type.type);
10064 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10066 if (klass->generic_container || (count == 0))
10069 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10071 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10073 klass->generic_container->owner.klass = klass;
10074 klass->generic_container->type_argc = count;
10075 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10077 klass->is_generic = 1;
10079 for (i = 0; i < count; i++) {
10080 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10081 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10082 klass->generic_container->type_params [i] = *param;
10083 /*Make sure we are a diferent type instance */
10084 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10085 klass->generic_container->type_params [i].info.pklass = NULL;
10086 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10088 g_assert (klass->generic_container->type_params [i].param.owner);
10091 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10095 * mono_reflection_create_internal_class:
10096 * @tb: a TypeBuilder object
10098 * Actually create the MonoClass that is associated with the TypeBuilder.
10101 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10105 MONO_ARCH_SAVE_REGS;
10107 klass = mono_class_from_mono_type (tb->type.type);
10109 mono_loader_lock ();
10110 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10111 MonoReflectionFieldBuilder *fb;
10113 MonoType *enum_basetype;
10115 g_assert (tb->fields != NULL);
10116 g_assert (mono_array_length (tb->fields) >= 1);
10118 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10120 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10121 mono_loader_unlock ();
10125 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10126 klass->element_class = mono_class_from_mono_type (enum_basetype);
10127 if (!klass->element_class)
10128 klass->element_class = mono_class_from_mono_type (enum_basetype);
10131 * get the element_class from the current corlib.
10133 ec = default_class_from_mono_type (enum_basetype);
10134 klass->instance_size = ec->instance_size;
10135 klass->size_inited = 1;
10137 * this is almost safe to do with enums and it's needed to be able
10138 * to create objects of the enum type (for use in SetConstant).
10140 /* FIXME: Does this mean enums can't have method overrides ? */
10141 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10143 mono_loader_unlock ();
10146 static MonoMarshalSpec*
10147 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10148 MonoReflectionMarshal *minfo)
10150 MonoMarshalSpec *res;
10152 res = image_g_new0 (image, MonoMarshalSpec, 1);
10153 res->native = minfo->type;
10155 switch (minfo->type) {
10156 case MONO_NATIVE_LPARRAY:
10157 res->data.array_data.elem_type = minfo->eltype;
10158 if (minfo->has_size) {
10159 res->data.array_data.param_num = minfo->param_num;
10160 res->data.array_data.num_elem = minfo->count;
10161 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10164 res->data.array_data.param_num = -1;
10165 res->data.array_data.num_elem = -1;
10166 res->data.array_data.elem_mult = -1;
10170 case MONO_NATIVE_BYVALTSTR:
10171 case MONO_NATIVE_BYVALARRAY:
10172 res->data.array_data.num_elem = minfo->count;
10175 case MONO_NATIVE_CUSTOM:
10176 if (minfo->marshaltyperef)
10177 res->data.custom_data.custom_name =
10178 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10179 if (minfo->mcookie)
10180 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10189 #endif /* !DISABLE_REFLECTION_EMIT */
10191 MonoReflectionMarshalAsAttribute*
10192 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10193 MonoMarshalSpec *spec)
10195 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10196 MonoReflectionMarshalAsAttribute *minfo;
10199 if (!System_Reflection_Emit_MarshalAsAttribute) {
10200 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10201 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10202 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10205 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10206 minfo->utype = spec->native;
10208 switch (minfo->utype) {
10209 case MONO_NATIVE_LPARRAY:
10210 minfo->array_subtype = spec->data.array_data.elem_type;
10211 minfo->size_const = spec->data.array_data.num_elem;
10212 if (spec->data.array_data.param_num != -1)
10213 minfo->size_param_index = spec->data.array_data.param_num;
10216 case MONO_NATIVE_BYVALTSTR:
10217 case MONO_NATIVE_BYVALARRAY:
10218 minfo->size_const = spec->data.array_data.num_elem;
10221 case MONO_NATIVE_CUSTOM:
10222 if (spec->data.custom_data.custom_name) {
10223 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10225 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10227 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10229 if (spec->data.custom_data.cookie)
10230 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10240 #ifndef DISABLE_REFLECTION_EMIT
10242 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10243 ReflectionMethodBuilder *rmb,
10244 MonoMethodSignature *sig)
10248 MonoMethodWrapper *wrapperm;
10249 MonoMarshalSpec **specs;
10250 MonoReflectionMethodAux *method_aux;
10255 mono_error_init (&error);
10257 * Methods created using a MethodBuilder should have their memory allocated
10258 * inside the image mempool, while dynamic methods should have their memory
10261 dynamic = rmb->refs != NULL;
10262 image = dynamic ? NULL : klass->image;
10265 g_assert (!klass->generic_class);
10267 mono_loader_lock ();
10269 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10270 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10271 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10273 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10275 wrapperm = (MonoMethodWrapper*)m;
10277 m->dynamic = dynamic;
10279 m->flags = rmb->attrs;
10280 m->iflags = rmb->iattrs;
10281 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10283 m->signature = sig;
10284 m->sre_method = TRUE;
10285 m->skip_visibility = rmb->skip_visibility;
10286 if (rmb->table_idx)
10287 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10289 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10290 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10291 m->string_ctor = 1;
10293 m->signature->pinvoke = 1;
10294 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10295 m->signature->pinvoke = 1;
10297 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10299 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10300 g_assert (mono_error_ok (&error));
10301 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10302 g_assert (mono_error_ok (&error));
10304 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10306 if (klass->image->dynamic)
10307 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10309 mono_loader_unlock ();
10312 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10313 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10314 MonoMethodHeader *header;
10316 gint32 max_stack, i;
10317 gint32 num_locals = 0;
10318 gint32 num_clauses = 0;
10322 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10323 code_size = rmb->ilgen->code_len;
10324 max_stack = rmb->ilgen->max_stack;
10325 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10326 if (rmb->ilgen->ex_handlers)
10327 num_clauses = method_count_clauses (rmb->ilgen);
10330 code = mono_array_addr (rmb->code, guint8, 0);
10331 code_size = mono_array_length (rmb->code);
10332 /* we probably need to run a verifier on the code... */
10342 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10343 header->code_size = code_size;
10344 header->code = image_g_malloc (image, code_size);
10345 memcpy ((char*)header->code, code, code_size);
10346 header->max_stack = max_stack;
10347 header->init_locals = rmb->init_locals;
10348 header->num_locals = num_locals;
10350 for (i = 0; i < num_locals; ++i) {
10351 MonoReflectionLocalBuilder *lb =
10352 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10354 header->locals [i] = image_g_new0 (image, MonoType, 1);
10355 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10358 header->num_clauses = num_clauses;
10360 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10361 rmb->ilgen, num_clauses);
10364 wrapperm->header = header;
10367 if (rmb->generic_params) {
10368 int count = mono_array_length (rmb->generic_params);
10369 MonoGenericContainer *container = rmb->generic_container;
10371 g_assert (container);
10373 container->type_argc = count;
10374 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10375 container->owner.method = m;
10377 m->is_generic = TRUE;
10378 mono_method_set_generic_container (m, container);
10380 for (i = 0; i < count; i++) {
10381 MonoReflectionGenericParam *gp =
10382 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10383 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10384 container->type_params [i] = *param;
10388 * The method signature might have pointers to generic parameters that belong to other methods.
10389 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10390 * generic parameters.
10392 for (i = 0; i < m->signature->param_count; ++i) {
10393 MonoType *t = m->signature->params [i];
10394 if (t->type == MONO_TYPE_MVAR) {
10395 MonoGenericParam *gparam = t->data.generic_param;
10396 if (gparam->num < count) {
10397 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10398 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10404 if (klass->generic_container) {
10405 container->parent = klass->generic_container;
10406 container->context.class_inst = klass->generic_container->context.class_inst;
10408 container->context.method_inst = mono_get_shared_generic_inst (container);
10412 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10416 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10418 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10419 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10420 for (i = 0; i < rmb->nrefs; ++i)
10421 data [i + 1] = rmb->refs [i];
10426 /* Parameter info */
10429 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10430 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10431 for (i = 0; i <= m->signature->param_count; ++i) {
10432 MonoReflectionParamBuilder *pb;
10433 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10434 if ((i > 0) && (pb->attrs)) {
10435 /* Make a copy since it might point to a shared type structure */
10436 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10437 m->signature->params [i - 1]->attrs = pb->attrs;
10440 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10441 MonoDynamicImage *assembly;
10442 guint32 idx, def_type, len;
10446 if (!method_aux->param_defaults) {
10447 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10448 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10450 assembly = (MonoDynamicImage*)klass->image;
10451 idx = encode_constant (assembly, pb->def_value, &def_type);
10452 /* Copy the data from the blob since it might get realloc-ed */
10453 p = assembly->blob.data + idx;
10454 len = mono_metadata_decode_blob_size (p, &p2);
10456 method_aux->param_defaults [i] = image_g_malloc (image, len);
10457 method_aux->param_default_types [i] = def_type;
10458 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10462 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10463 g_assert (mono_error_ok (&error));
10466 if (!method_aux->param_cattr)
10467 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10468 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10474 /* Parameter marshalling */
10477 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10478 MonoReflectionParamBuilder *pb;
10479 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10480 if (pb->marshal_info) {
10482 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10483 specs [pb->position] =
10484 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10488 if (specs != NULL) {
10490 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10491 method_aux->param_marshall = specs;
10494 if (klass->image->dynamic && method_aux)
10495 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10497 mono_loader_unlock ();
10503 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10505 ReflectionMethodBuilder rmb;
10506 MonoMethodSignature *sig;
10508 mono_loader_lock ();
10509 sig = ctor_builder_to_signature (klass->image, mb);
10510 mono_loader_unlock ();
10512 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10514 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10515 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10517 /* If we are in a generic class, we might be called multiple times from inflate_method */
10518 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10519 /* ilgen is no longer needed */
10523 return mb->mhandle;
10527 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10529 ReflectionMethodBuilder rmb;
10530 MonoMethodSignature *sig;
10532 mono_loader_lock ();
10533 sig = method_builder_to_signature (klass->image, mb);
10534 mono_loader_unlock ();
10536 reflection_methodbuilder_from_method_builder (&rmb, mb);
10538 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10539 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10541 /* If we are in a generic class, we might be called multiple times from inflate_method */
10542 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10543 /* ilgen is no longer needed */
10546 return mb->mhandle;
10549 static MonoClassField*
10550 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10552 MonoClassField *field;
10556 field = g_new0 (MonoClassField, 1);
10558 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10559 g_assert (mono_error_ok (&error));
10560 if (fb->attrs || fb->modreq || fb->modopt) {
10561 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10562 field->type->attrs = fb->attrs;
10564 g_assert (klass->image->dynamic);
10565 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10566 g_free (field->type);
10567 field->type = mono_metadata_type_dup (klass->image, custom);
10570 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10572 if (fb->offset != -1)
10573 field->offset = fb->offset;
10574 field->parent = klass;
10575 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10577 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10584 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10587 MonoReflectionTypeBuilder *tb = NULL;
10588 gboolean is_dynamic = FALSE;
10589 MonoDomain *domain;
10590 MonoClass *geninst;
10592 mono_loader_lock ();
10594 domain = mono_object_domain (type);
10596 if (is_sre_type_builder (mono_object_class (type))) {
10597 tb = (MonoReflectionTypeBuilder *) type;
10600 } else if (is_sre_generic_instance (mono_object_class (type))) {
10601 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10602 MonoReflectionType *gtd = rgi->generic_type;
10604 if (is_sre_type_builder (mono_object_class (gtd))) {
10605 tb = (MonoReflectionTypeBuilder *)gtd;
10610 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10611 if (tb && tb->generic_container)
10612 mono_reflection_create_generic_class (tb);
10614 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10615 if (!klass->generic_container) {
10616 mono_loader_unlock ();
10620 if (klass->wastypebuilder) {
10621 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10626 mono_loader_unlock ();
10628 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10630 return &geninst->byval_arg;
10634 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10636 MonoGenericClass *gclass;
10637 MonoGenericInst *inst;
10639 g_assert (klass->generic_container);
10641 inst = mono_metadata_get_generic_inst (type_argc, types);
10642 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10644 return mono_generic_class_get_class (gclass);
10647 MonoReflectionMethod*
10648 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10651 MonoMethod *method, *inflated;
10652 MonoMethodInflated *imethod;
10653 MonoGenericContext tmp_context;
10654 MonoGenericInst *ginst;
10655 MonoType **type_argv;
10658 MONO_ARCH_SAVE_REGS;
10660 /*FIXME but this no longer should happen*/
10661 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10662 #ifndef DISABLE_REFLECTION_EMIT
10663 MonoReflectionMethodBuilder *mb = NULL;
10664 MonoReflectionTypeBuilder *tb;
10667 mb = (MonoReflectionMethodBuilder *) rmethod;
10668 tb = (MonoReflectionTypeBuilder *) mb->type;
10669 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10671 method = methodbuilder_to_mono_method (klass, mb);
10673 g_assert_not_reached ();
10677 method = rmethod->method;
10680 klass = method->klass;
10682 if (method->is_inflated)
10683 method = ((MonoMethodInflated *) method)->declaring;
10685 count = mono_method_signature (method)->generic_param_count;
10686 if (count != mono_array_length (types))
10689 type_argv = g_new0 (MonoType *, count);
10690 for (i = 0; i < count; i++) {
10691 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10692 type_argv [i] = mono_reflection_type_get_handle (garg);
10694 ginst = mono_metadata_get_generic_inst (count, type_argv);
10695 g_free (type_argv);
10697 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10698 tmp_context.method_inst = ginst;
10700 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10701 imethod = (MonoMethodInflated *) inflated;
10703 /*FIXME but I think this is no longer necessary*/
10704 if (method->klass->image->dynamic) {
10705 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10707 * This table maps metadata structures representing inflated methods/fields
10708 * to the reflection objects representing their generic definitions.
10710 mono_image_lock ((MonoImage*)image);
10711 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10712 mono_image_unlock ((MonoImage*)image);
10715 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10716 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10718 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10721 #ifndef DISABLE_REFLECTION_EMIT
10723 static MonoMethod *
10724 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10726 MonoMethodInflated *imethod;
10727 MonoGenericContext *context;
10731 * With generic code sharing the klass might not be inflated.
10732 * This can happen because classes inflated with their own
10733 * type arguments are "normalized" to the uninflated class.
10735 if (!klass->generic_class)
10738 context = mono_class_get_context (klass);
10740 if (klass->method.count && klass->methods) {
10741 /* Find the already created inflated method */
10742 for (i = 0; i < klass->method.count; ++i) {
10743 g_assert (klass->methods [i]->is_inflated);
10744 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10747 g_assert (i < klass->method.count);
10748 imethod = (MonoMethodInflated*)klass->methods [i];
10750 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10753 if (method->is_generic && method->klass->image->dynamic) {
10754 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10756 mono_image_lock ((MonoImage*)image);
10757 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10758 mono_image_unlock ((MonoImage*)image);
10760 return (MonoMethod *) imethod;
10763 static MonoMethod *
10764 inflate_method (MonoReflectionType *type, MonoObject *obj)
10766 MonoMethod *method;
10769 MonoClass *type_class = mono_object_class (type);
10771 if (is_sre_generic_instance (type_class)) {
10772 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10773 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10774 } else if (is_sre_type_builder (type_class)) {
10775 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10776 } else if (type->type) {
10777 gklass = mono_class_from_mono_type (type->type);
10778 gklass = mono_class_get_generic_type_definition (gklass);
10780 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10783 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10784 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10785 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10787 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10788 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10789 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10790 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10791 method = ((MonoReflectionMethod *) obj)->method;
10793 method = NULL; /* prevent compiler warning */
10794 g_error ("can't handle type %s", obj->vtable->klass->name);
10797 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10800 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10802 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10804 MonoGenericClass *gclass;
10805 MonoDynamicGenericClass *dgclass;
10806 MonoClass *klass, *gklass;
10810 MONO_ARCH_SAVE_REGS;
10812 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10813 klass = mono_class_from_mono_type (gtype);
10814 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10815 gclass = gtype->data.generic_class;
10817 if (!gclass->is_dynamic)
10820 dgclass = (MonoDynamicGenericClass *) gclass;
10822 if (dgclass->initialized)
10825 gklass = gclass->container_class;
10826 mono_class_init (gklass);
10828 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10830 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10831 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10832 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10834 for (i = 0; i < dgclass->count_fields; i++) {
10835 MonoObject *obj = mono_array_get (fields, gpointer, i);
10836 MonoClassField *field, *inflated_field = NULL;
10838 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10839 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10840 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10841 field = ((MonoReflectionField *) obj)->field;
10843 field = NULL; /* prevent compiler warning */
10844 g_assert_not_reached ();
10847 dgclass->fields [i] = *field;
10848 dgclass->fields [i].parent = klass;
10849 dgclass->fields [i].type = mono_class_inflate_generic_type (
10850 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10851 dgclass->field_generic_types [i] = field->type;
10852 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10853 dgclass->field_objects [i] = obj;
10855 if (inflated_field) {
10856 g_free (inflated_field);
10858 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10862 dgclass->initialized = TRUE;
10866 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10868 MonoDynamicGenericClass *dgclass;
10871 g_assert (gclass->is_dynamic);
10873 dgclass = (MonoDynamicGenericClass *)gclass;
10875 for (i = 0; i < dgclass->count_fields; ++i) {
10876 MonoClassField *field = dgclass->fields + i;
10877 mono_metadata_free_type (field->type);
10878 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10883 fix_partial_generic_class (MonoClass *klass)
10885 MonoClass *gklass = klass->generic_class->container_class;
10886 MonoDynamicGenericClass *dgclass;
10889 if (klass->wastypebuilder)
10892 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10893 if (klass->parent != gklass->parent) {
10895 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10896 if (mono_error_ok (&error)) {
10897 MonoClass *parent = mono_class_from_mono_type (parent_type);
10898 mono_metadata_free_type (parent_type);
10899 if (parent != klass->parent) {
10900 /*fool mono_class_setup_parent*/
10901 klass->supertypes = NULL;
10902 mono_class_setup_parent (klass, parent);
10905 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10906 mono_error_cleanup (&error);
10907 if (gklass->wastypebuilder)
10908 klass->wastypebuilder = TRUE;
10913 if (!dgclass->initialized)
10916 if (klass->method.count != gklass->method.count) {
10917 klass->method.count = gklass->method.count;
10918 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10920 for (i = 0; i < klass->method.count; i++) {
10921 klass->methods [i] = mono_class_inflate_generic_method_full (
10922 gklass->methods [i], klass, mono_class_get_context (klass));
10926 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10927 klass->interface_count = gklass->interface_count;
10928 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10929 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10931 for (i = 0; i < gklass->interface_count; ++i) {
10932 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10933 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10934 mono_metadata_free_type (iface_type);
10936 ensure_runtime_vtable (klass->interfaces [i]);
10938 klass->interfaces_inited = 1;
10941 if (klass->field.count != gklass->field.count) {
10942 klass->field.count = gklass->field.count;
10943 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10945 for (i = 0; i < klass->field.count; i++) {
10946 klass->fields [i] = gklass->fields [i];
10947 klass->fields [i].parent = klass;
10948 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10952 /*We can only finish with this klass once it's parent has as well*/
10953 if (gklass->wastypebuilder)
10954 klass->wastypebuilder = TRUE;
10959 ensure_generic_class_runtime_vtable (MonoClass *klass)
10961 MonoClass *gklass = klass->generic_class->container_class;
10963 ensure_runtime_vtable (gklass);
10965 fix_partial_generic_class (klass);
10969 ensure_runtime_vtable (MonoClass *klass)
10971 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10974 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10977 ensure_runtime_vtable (klass->parent);
10980 num = tb->ctors? mono_array_length (tb->ctors): 0;
10981 num += tb->num_methods;
10982 klass->method.count = num;
10983 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10984 num = tb->ctors? mono_array_length (tb->ctors): 0;
10985 for (i = 0; i < num; ++i)
10986 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10987 num = tb->num_methods;
10989 for (i = 0; i < num; ++i)
10990 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10992 if (tb->interfaces) {
10993 klass->interface_count = mono_array_length (tb->interfaces);
10994 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10995 for (i = 0; i < klass->interface_count; ++i) {
10996 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10997 klass->interfaces [i] = mono_class_from_mono_type (iface);
10998 ensure_runtime_vtable (klass->interfaces [i]);
11000 klass->interfaces_inited = 1;
11002 } else if (klass->generic_class){
11003 ensure_generic_class_runtime_vtable (klass);
11006 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11008 for (i = 0; i < klass->method.count; ++i) {
11009 MonoMethod *im = klass->methods [i];
11010 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11011 im->slot = slot_num++;
11014 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11015 mono_class_setup_interface_offsets (klass);
11016 mono_class_setup_interface_id (klass);
11020 * The generic vtable is needed even if image->run is not set since some
11021 * runtime code like ves_icall_Type_GetMethodsByName depends on
11022 * method->slot being defined.
11026 * tb->methods could not be freed since it is used for determining
11027 * overrides during dynamic vtable construction.
11032 mono_reflection_method_get_handle (MonoObject *method)
11034 MonoClass *class = mono_object_class (method);
11035 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11036 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11037 return sr_method->method;
11039 if (is_sre_method_builder (class)) {
11040 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11041 return mb->mhandle;
11043 if (is_sre_method_on_tb_inst (class)) {
11044 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11045 MonoMethod *result;
11046 /*FIXME move this to a proper method and unify with resolve_object*/
11047 if (m->method_args) {
11048 result = mono_reflection_method_on_tb_inst_get_handle (m);
11050 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11051 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11052 MonoMethod *mono_method;
11054 if (is_sre_method_builder (mono_object_class (m->mb)))
11055 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11056 else if (is_sr_mono_method (mono_object_class (m->mb)))
11057 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11059 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)));
11061 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11066 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11071 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11073 MonoReflectionTypeBuilder *tb;
11075 MonoReflectionMethod *m;
11078 *num_overrides = 0;
11080 g_assert (klass->image->dynamic);
11082 if (!mono_class_get_ref_info (klass))
11085 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11087 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11091 for (i = 0; i < tb->num_methods; ++i) {
11092 MonoReflectionMethodBuilder *mb =
11093 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11094 if (mb->override_methods)
11095 onum += mono_array_length (mb->override_methods);
11100 *overrides = g_new0 (MonoMethod*, onum * 2);
11103 for (i = 0; i < tb->num_methods; ++i) {
11104 MonoReflectionMethodBuilder *mb =
11105 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11106 if (mb->override_methods) {
11107 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11108 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11110 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11111 (*overrides) [onum * 2 + 1] = mb->mhandle;
11113 g_assert (mb->mhandle);
11121 *num_overrides = onum;
11125 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11127 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11128 MonoReflectionFieldBuilder *fb;
11129 MonoClassField *field;
11130 MonoImage *image = klass->image;
11131 const char *p, *p2;
11133 guint32 len, idx, real_size = 0;
11135 klass->field.count = tb->num_fields;
11136 klass->field.first = 0;
11138 mono_error_init (error);
11140 if (tb->class_size) {
11141 if ((tb->packing_size & 0xfffffff0) != 0) {
11142 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11143 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11146 klass->packing_size = tb->packing_size;
11147 real_size = klass->instance_size + tb->class_size;
11150 if (!klass->field.count) {
11151 klass->instance_size = MAX (klass->instance_size, real_size);
11155 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11156 mono_class_alloc_ext (klass);
11157 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11159 This is, guess what, a hack.
11160 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11161 On the static path no field class is resolved, only types are built. This is the right thing to do
11163 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11165 klass->size_inited = 1;
11167 for (i = 0; i < klass->field.count; ++i) {
11168 MonoArray *rva_data;
11169 fb = mono_array_get (tb->fields, gpointer, i);
11170 field = &klass->fields [i];
11171 field->name = mono_string_to_utf8_image (image, fb->name, error);
11172 if (!mono_error_ok (error))
11175 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11176 field->type->attrs = fb->attrs;
11178 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11181 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11182 char *base = mono_array_addr (rva_data, char, 0);
11183 size_t size = mono_array_length (rva_data);
11184 char *data = mono_image_alloc (klass->image, size);
11185 memcpy (data, base, size);
11186 klass->ext->field_def_values [i].data = data;
11188 if (fb->offset != -1)
11189 field->offset = fb->offset;
11190 field->parent = klass;
11191 fb->handle = field;
11192 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11194 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11195 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11197 if (fb->def_value) {
11198 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11199 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11200 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11201 /* Copy the data from the blob since it might get realloc-ed */
11202 p = assembly->blob.data + idx;
11203 len = mono_metadata_decode_blob_size (p, &p2);
11205 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11206 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11210 klass->instance_size = MAX (klass->instance_size, real_size);
11211 mono_class_layout_fields (klass);
11215 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11217 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11218 MonoReflectionPropertyBuilder *pb;
11219 MonoImage *image = klass->image;
11220 MonoProperty *properties;
11223 mono_error_init (error);
11226 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11228 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11229 klass->ext->property.first = 0;
11231 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11232 klass->ext->properties = properties;
11233 for (i = 0; i < klass->ext->property.count; ++i) {
11234 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11235 properties [i].parent = klass;
11236 properties [i].attrs = pb->attrs;
11237 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11238 if (!mono_error_ok (error))
11240 if (pb->get_method)
11241 properties [i].get = pb->get_method->mhandle;
11242 if (pb->set_method)
11243 properties [i].set = pb->set_method->mhandle;
11245 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11246 if (pb->def_value) {
11248 const char *p, *p2;
11249 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11250 if (!klass->ext->prop_def_values)
11251 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11252 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11253 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11254 /* Copy the data from the blob since it might get realloc-ed */
11255 p = assembly->blob.data + idx;
11256 len = mono_metadata_decode_blob_size (p, &p2);
11258 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11259 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11264 MonoReflectionEvent *
11265 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11267 MonoEvent *event = g_new0 (MonoEvent, 1);
11270 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11272 event->parent = klass;
11273 event->attrs = eb->attrs;
11274 event->name = mono_string_to_utf8 (eb->name);
11275 if (eb->add_method)
11276 event->add = eb->add_method->mhandle;
11277 if (eb->remove_method)
11278 event->remove = eb->remove_method->mhandle;
11279 if (eb->raise_method)
11280 event->raise = eb->raise_method->mhandle;
11282 #ifndef MONO_SMALL_CONFIG
11283 if (eb->other_methods) {
11285 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11286 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11287 MonoReflectionMethodBuilder *mb =
11288 mono_array_get (eb->other_methods,
11289 MonoReflectionMethodBuilder*, j);
11290 event->other [j] = mb->mhandle;
11295 return mono_event_get_object (mono_object_domain (tb), klass, event);
11299 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11301 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11302 MonoReflectionEventBuilder *eb;
11303 MonoImage *image = klass->image;
11307 mono_error_init (error);
11310 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11312 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11313 klass->ext->event.first = 0;
11315 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11316 klass->ext->events = events;
11317 for (i = 0; i < klass->ext->event.count; ++i) {
11318 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11319 events [i].parent = klass;
11320 events [i].attrs = eb->attrs;
11321 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11322 if (!mono_error_ok (error))
11324 if (eb->add_method)
11325 events [i].add = eb->add_method->mhandle;
11326 if (eb->remove_method)
11327 events [i].remove = eb->remove_method->mhandle;
11328 if (eb->raise_method)
11329 events [i].raise = eb->raise_method->mhandle;
11331 #ifndef MONO_SMALL_CONFIG
11332 if (eb->other_methods) {
11334 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11335 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11336 MonoReflectionMethodBuilder *mb =
11337 mono_array_get (eb->other_methods,
11338 MonoReflectionMethodBuilder*, j);
11339 events [i].other [j] = mb->mhandle;
11343 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11348 remove_instantiations_of_and_ensure_contents (gpointer key,
11350 gpointer user_data)
11352 MonoType *type = (MonoType*)key;
11353 MonoClass *klass = (MonoClass*)user_data;
11355 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11356 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11363 check_array_for_usertypes (MonoArray *arr)
11370 for (i = 0; i < mono_array_length (arr); ++i)
11371 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11374 MonoReflectionType*
11375 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11379 MonoDomain* domain;
11380 MonoReflectionType* res;
11383 MONO_ARCH_SAVE_REGS;
11385 domain = mono_object_domain (tb);
11386 klass = mono_class_from_mono_type (tb->type.type);
11389 * Check for user defined Type subclasses.
11391 RESOLVE_TYPE (tb->parent);
11392 check_array_for_usertypes (tb->interfaces);
11394 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11395 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11397 RESOLVE_TYPE (fb->type);
11398 check_array_for_usertypes (fb->modreq);
11399 check_array_for_usertypes (fb->modopt);
11400 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11401 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11406 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11407 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11409 RESOLVE_TYPE (mb->rtype);
11410 check_array_for_usertypes (mb->return_modreq);
11411 check_array_for_usertypes (mb->return_modopt);
11412 check_array_for_usertypes (mb->parameters);
11413 if (mb->param_modreq)
11414 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11415 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11416 if (mb->param_modopt)
11417 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11418 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11423 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11424 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11426 check_array_for_usertypes (mb->parameters);
11427 if (mb->param_modreq)
11428 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11429 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11430 if (mb->param_modopt)
11431 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11432 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11437 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11440 * we need to lock the domain because the lock will be taken inside
11441 * So, we need to keep the locking order correct.
11443 mono_loader_lock ();
11444 mono_domain_lock (domain);
11445 if (klass->wastypebuilder) {
11446 mono_domain_unlock (domain);
11447 mono_loader_unlock ();
11448 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11451 * Fields to set in klass:
11452 * the various flags: delegate/unicode/contextbound etc.
11454 klass->flags = tb->attrs;
11455 klass->has_cctor = 1;
11456 klass->has_finalize = 1;
11457 klass->has_finalize_inited = 1;
11459 /* fool mono_class_setup_parent */
11460 klass->supertypes = NULL;
11461 mono_class_setup_parent (klass, klass->parent);
11462 mono_class_setup_mono_type (klass);
11465 if (!((MonoDynamicImage*)klass->image)->run) {
11466 if (klass->generic_container) {
11467 /* FIXME: The code below can't handle generic classes */
11468 klass->wastypebuilder = TRUE;
11469 mono_loader_unlock ();
11470 mono_domain_unlock (domain);
11471 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11476 /* enums are done right away */
11477 if (!klass->enumtype)
11478 ensure_runtime_vtable (klass);
11480 if (tb->subtypes) {
11481 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11482 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11483 mono_class_alloc_ext (klass);
11484 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)));
11488 klass->nested_classes_inited = TRUE;
11490 /* fields and object layout */
11491 if (klass->parent) {
11492 if (!klass->parent->size_inited)
11493 mono_class_init (klass->parent);
11494 klass->instance_size = klass->parent->instance_size;
11495 klass->sizes.class_size = 0;
11496 klass->min_align = klass->parent->min_align;
11497 /* if the type has no fields we won't call the field_setup
11498 * routine which sets up klass->has_references.
11500 klass->has_references |= klass->parent->has_references;
11502 klass->instance_size = sizeof (MonoObject);
11503 klass->min_align = 1;
11506 /* FIXME: handle packing_size and instance_size */
11507 typebuilder_setup_fields (klass, &error);
11508 if (!mono_error_ok (&error))
11510 typebuilder_setup_properties (klass, &error);
11511 if (!mono_error_ok (&error))
11514 typebuilder_setup_events (klass, &error);
11515 if (!mono_error_ok (&error))
11518 klass->wastypebuilder = TRUE;
11521 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11522 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11523 * we want to return normal System.MonoType objects, so clear these out from the cache.
11525 * Together with this we must ensure the contents of all instances to match the created type.
11527 if (domain->type_hash && klass->generic_container)
11528 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11530 mono_domain_unlock (domain);
11531 mono_loader_unlock ();
11533 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11534 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11535 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11538 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11539 g_assert (res != (MonoReflectionType*)tb);
11544 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11545 klass->wastypebuilder = TRUE;
11546 mono_domain_unlock (domain);
11547 mono_loader_unlock ();
11548 mono_error_raise_exception (&error);
11553 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11555 MonoGenericParamFull *param;
11560 MONO_ARCH_SAVE_REGS;
11562 image = &gparam->tbuilder->module->dynamic_image->image;
11564 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11566 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11567 g_assert (mono_error_ok (&error));
11568 param->param.num = gparam->index;
11570 if (gparam->mbuilder) {
11571 if (!gparam->mbuilder->generic_container) {
11572 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11573 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11574 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11575 gparam->mbuilder->generic_container->is_method = TRUE;
11577 * Cannot set owner.method, since the MonoMethod is not created yet.
11578 * Set the image field instead, so type_in_image () works.
11580 gparam->mbuilder->generic_container->image = klass->image;
11582 param->param.owner = gparam->mbuilder->generic_container;
11583 } else if (gparam->tbuilder) {
11584 if (!gparam->tbuilder->generic_container) {
11585 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11586 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11587 gparam->tbuilder->generic_container->owner.klass = klass;
11589 param->param.owner = gparam->tbuilder->generic_container;
11592 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11594 gparam->type.type = &pklass->byval_arg;
11596 mono_class_set_ref_info (pklass, gparam);
11597 mono_image_append_class_to_reflection_info_set (pklass);
11601 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11603 MonoReflectionModuleBuilder *module = sig->module;
11604 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11605 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11610 check_array_for_usertypes (sig->arguments);
11612 sigbuffer_init (&buf, 32);
11614 sigbuffer_add_value (&buf, 0x07);
11615 sigbuffer_add_value (&buf, na);
11616 if (assembly != NULL){
11617 for (i = 0; i < na; ++i) {
11618 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11619 encode_reflection_type (assembly, type, &buf);
11623 buflen = buf.p - buf.buf;
11624 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11625 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11626 sigbuffer_free (&buf);
11632 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11634 MonoDynamicImage *assembly = sig->module->dynamic_image;
11635 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11640 check_array_for_usertypes (sig->arguments);
11642 sigbuffer_init (&buf, 32);
11644 sigbuffer_add_value (&buf, 0x06);
11645 for (i = 0; i < na; ++i) {
11646 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11647 encode_reflection_type (assembly, type, &buf);
11650 buflen = buf.p - buf.buf;
11651 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11652 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11653 sigbuffer_free (&buf);
11659 MonoMethod *handle;
11660 MonoDomain *domain;
11661 } DynamicMethodReleaseData;
11664 * The runtime automatically clean up those after finalization.
11666 static MonoReferenceQueue *dynamic_method_queue;
11669 free_dynamic_method (void *dynamic_method)
11671 DynamicMethodReleaseData *data = dynamic_method;
11673 mono_runtime_free_method (data->domain, data->handle);
11678 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11680 MonoReferenceQueue *queue;
11681 MonoMethod *handle;
11682 DynamicMethodReleaseData *release_data;
11683 ReflectionMethodBuilder rmb;
11684 MonoMethodSignature *sig;
11689 if (mono_runtime_is_shutting_down ())
11690 mono_raise_exception (mono_get_exception_invalid_operation (""));
11692 if (!(queue = dynamic_method_queue)) {
11693 mono_loader_lock ();
11694 if (!(queue = dynamic_method_queue))
11695 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11696 mono_loader_unlock ();
11699 sig = dynamic_method_to_signature (mb);
11701 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11704 * Resolve references.
11707 * Every second entry in the refs array is reserved for storing handle_class,
11708 * which is needed by the ldtoken implementation in the JIT.
11710 rmb.nrefs = mb->nrefs;
11711 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11712 for (i = 0; i < mb->nrefs; i += 2) {
11713 MonoClass *handle_class;
11715 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11717 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11718 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11720 * The referenced DynamicMethod should already be created by the managed
11721 * code, except in the case of circular references. In that case, we store
11722 * method in the refs array, and fix it up later when the referenced
11723 * DynamicMethod is created.
11725 if (method->mhandle) {
11726 ref = method->mhandle;
11728 /* FIXME: GC object stored in unmanaged memory */
11731 /* FIXME: GC object stored in unmanaged memory */
11732 method->referenced_by = g_slist_append (method->referenced_by, mb);
11734 handle_class = mono_defaults.methodhandle_class;
11736 MonoException *ex = NULL;
11737 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11739 ex = mono_get_exception_type_load (NULL, NULL);
11740 else if (mono_security_core_clr_enabled ())
11741 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11745 mono_raise_exception (ex);
11750 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11751 rmb.refs [i + 1] = handle_class;
11754 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11756 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11757 release_data = g_new (DynamicMethodReleaseData, 1);
11758 release_data->handle = handle;
11759 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11760 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11761 g_free (release_data);
11763 /* Fix up refs entries pointing at us */
11764 for (l = mb->referenced_by; l; l = l->next) {
11765 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11766 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11769 g_assert (method->mhandle);
11771 data = (gpointer*)wrapper->method_data;
11772 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11773 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11774 data [i + 1] = mb->mhandle;
11777 g_slist_free (mb->referenced_by);
11781 /* ilgen is no longer needed */
11785 #endif /* DISABLE_REFLECTION_EMIT */
11789 * mono_reflection_is_valid_dynamic_token:
11791 * Returns TRUE if token is valid.
11795 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11797 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11800 MonoMethodSignature *
11801 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11803 MonoMethodSignature *sig;
11804 g_assert (image->dynamic);
11806 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11810 return mono_method_signature (method);
11813 #ifndef DISABLE_REFLECTION_EMIT
11816 * mono_reflection_lookup_dynamic_token:
11818 * Finish the Builder object pointed to by TOKEN and return the corresponding
11819 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11820 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11823 * LOCKING: Take the loader lock
11826 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11828 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11832 mono_loader_lock ();
11833 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11834 mono_loader_unlock ();
11837 g_error ("Could not find required dynamic token 0x%08x", token);
11843 handle_class = &klass;
11844 return resolve_object (image, obj, handle_class, context);
11848 * ensure_complete_type:
11850 * Ensure that KLASS is completed if it is a dynamic type, or references
11854 ensure_complete_type (MonoClass *klass)
11856 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11857 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11859 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11861 // Asserting here could break a lot of code
11862 //g_assert (klass->wastypebuilder);
11865 if (klass->generic_class) {
11866 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11869 for (i = 0; i < inst->type_argc; ++i) {
11870 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11876 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11878 gpointer result = NULL;
11880 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11881 result = mono_string_intern ((MonoString*)obj);
11882 *handle_class = mono_defaults.string_class;
11884 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11885 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11886 MonoClass *mc = mono_class_from_mono_type (type);
11887 if (!mono_class_init (mc))
11888 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11891 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11892 result = mono_class_from_mono_type (inflated);
11893 mono_metadata_free_type (inflated);
11895 result = mono_class_from_mono_type (type);
11897 *handle_class = mono_defaults.typehandle_class;
11899 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11900 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11901 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11902 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11903 result = ((MonoReflectionMethod*)obj)->method;
11905 result = mono_class_inflate_generic_method (result, context);
11906 *handle_class = mono_defaults.methodhandle_class;
11908 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11909 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11910 result = mb->mhandle;
11912 /* Type is not yet created */
11913 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11915 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11918 * Hopefully this has been filled in by calling CreateType() on the
11922 * TODO: This won't work if the application finishes another
11923 * TypeBuilder instance instead of this one.
11925 result = mb->mhandle;
11928 result = mono_class_inflate_generic_method (result, context);
11929 *handle_class = mono_defaults.methodhandle_class;
11930 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11931 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11933 result = cb->mhandle;
11935 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11937 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11938 result = cb->mhandle;
11941 result = mono_class_inflate_generic_method (result, context);
11942 *handle_class = mono_defaults.methodhandle_class;
11943 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11944 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11946 ensure_complete_type (field->parent);
11948 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11949 MonoClass *class = mono_class_from_mono_type (inflated);
11950 MonoClassField *inflated_field;
11951 gpointer iter = NULL;
11952 mono_metadata_free_type (inflated);
11953 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11954 if (!strcmp (field->name, inflated_field->name))
11957 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11958 result = inflated_field;
11962 *handle_class = mono_defaults.fieldhandle_class;
11964 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11965 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11966 result = fb->handle;
11969 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11971 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11972 result = fb->handle;
11975 if (fb->handle && fb->handle->parent->generic_container) {
11976 MonoClass *klass = fb->handle->parent;
11977 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11978 MonoClass *inflated = mono_class_from_mono_type (type);
11980 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11982 mono_metadata_free_type (type);
11984 *handle_class = mono_defaults.fieldhandle_class;
11985 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11986 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11987 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11990 klass = type->data.klass;
11991 if (klass->wastypebuilder) {
11992 /* Already created */
11996 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11997 result = type->data.klass;
12000 *handle_class = mono_defaults.typehandle_class;
12001 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12002 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12003 MonoMethodSignature *sig;
12006 if (helper->arguments)
12007 nargs = mono_array_length (helper->arguments);
12011 sig = mono_metadata_signature_alloc (image, nargs);
12012 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12013 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12015 if (helper->unmanaged_call_conv) { /* unmanaged */
12016 sig->call_convention = helper->unmanaged_call_conv - 1;
12017 sig->pinvoke = TRUE;
12018 } else if (helper->call_conv & 0x02) {
12019 sig->call_convention = MONO_CALL_VARARG;
12021 sig->call_convention = MONO_CALL_DEFAULT;
12024 sig->param_count = nargs;
12025 /* TODO: Copy type ? */
12026 sig->ret = helper->return_type->type;
12027 for (i = 0; i < nargs; ++i)
12028 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12031 *handle_class = NULL;
12032 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12033 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12034 /* Already created by the managed code */
12035 g_assert (method->mhandle);
12036 result = method->mhandle;
12037 *handle_class = mono_defaults.methodhandle_class;
12038 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12039 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12040 type = mono_class_inflate_generic_type (type, context);
12041 result = mono_class_from_mono_type (type);
12042 *handle_class = mono_defaults.typehandle_class;
12044 mono_metadata_free_type (type);
12045 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12046 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12047 type = mono_class_inflate_generic_type (type, context);
12048 result = mono_class_from_mono_type (type);
12049 *handle_class = mono_defaults.typehandle_class;
12051 mono_metadata_free_type (type);
12052 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12053 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12054 MonoClass *inflated;
12056 MonoClassField *field;
12058 if (is_sre_field_builder (mono_object_class (f->fb)))
12059 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12060 else if (is_sr_mono_field (mono_object_class (f->fb)))
12061 field = ((MonoReflectionField*)f->fb)->field;
12063 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)));
12065 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12066 inflated = mono_class_from_mono_type (type);
12068 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12069 ensure_complete_type (field->parent);
12071 mono_metadata_free_type (type);
12072 *handle_class = mono_defaults.fieldhandle_class;
12073 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12074 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12075 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12076 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12077 MonoMethod *method;
12079 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12080 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12081 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12082 method = ((MonoReflectionMethod *)c->cb)->method;
12084 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)));
12086 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12087 *handle_class = mono_defaults.methodhandle_class;
12088 mono_metadata_free_type (type);
12089 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12090 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12091 if (m->method_args) {
12092 result = mono_reflection_method_on_tb_inst_get_handle (m);
12094 result = mono_class_inflate_generic_method (result, context);
12096 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12097 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12098 MonoMethod *method;
12100 if (is_sre_method_builder (mono_object_class (m->mb)))
12101 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12102 else if (is_sr_mono_method (mono_object_class (m->mb)))
12103 method = ((MonoReflectionMethod *)m->mb)->method;
12105 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)));
12107 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12108 mono_metadata_free_type (type);
12110 *handle_class = mono_defaults.methodhandle_class;
12111 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12112 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12115 MonoMethod *method;
12119 mtype = mono_reflection_type_get_handle (m->parent);
12120 klass = mono_class_from_mono_type (mtype);
12122 /* Find the method */
12124 name = mono_string_to_utf8 (m->name);
12126 while ((method = mono_class_get_methods (klass, &iter))) {
12127 if (!strcmp (method->name, name))
12134 // FIXME: Check parameters/return value etc. match
12137 *handle_class = mono_defaults.methodhandle_class;
12138 } else if (is_sre_array (mono_object_get_class(obj)) ||
12139 is_sre_byref (mono_object_get_class(obj)) ||
12140 is_sre_pointer (mono_object_get_class(obj))) {
12141 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12142 MonoType *type = mono_reflection_type_get_handle (ref_type);
12145 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12146 result = mono_class_from_mono_type (inflated);
12147 mono_metadata_free_type (inflated);
12149 result = mono_class_from_mono_type (type);
12151 *handle_class = mono_defaults.typehandle_class;
12153 g_print ("%s\n", obj->vtable->klass->name);
12154 g_assert_not_reached ();
12159 #else /* DISABLE_REFLECTION_EMIT */
12162 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12164 g_assert_not_reached ();
12169 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12171 g_assert_not_reached ();
12175 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12177 g_assert_not_reached ();
12181 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12183 g_assert_not_reached ();
12187 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12189 g_assert_not_reached ();
12193 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12195 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12199 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12201 g_assert_not_reached ();
12205 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12207 g_assert_not_reached ();
12210 MonoReflectionModule *
12211 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12213 g_assert_not_reached ();
12218 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12220 g_assert_not_reached ();
12225 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12227 g_assert_not_reached ();
12232 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12233 gboolean create_open_instance, gboolean register_token)
12235 g_assert_not_reached ();
12240 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12245 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12247 g_assert_not_reached ();
12251 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12254 *num_overrides = 0;
12257 MonoReflectionEvent *
12258 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12260 g_assert_not_reached ();
12264 MonoReflectionType*
12265 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12267 g_assert_not_reached ();
12272 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12274 g_assert_not_reached ();
12278 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12280 g_assert_not_reached ();
12285 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12287 g_assert_not_reached ();
12292 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12297 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12303 mono_reflection_type_get_handle (MonoReflectionType* ref)
12311 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12313 g_assert_not_reached ();
12316 #endif /* DISABLE_REFLECTION_EMIT */
12318 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12319 const static guint32 declsec_flags_map[] = {
12320 0x00000000, /* empty */
12321 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12322 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12323 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12324 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12325 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12326 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12327 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12328 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12329 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12330 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12331 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12332 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12333 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12334 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12335 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12336 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12337 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12338 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12342 * Returns flags that includes all available security action associated to the handle.
12343 * @token: metadata token (either for a class or a method)
12344 * @image: image where resides the metadata.
12347 mono_declsec_get_flags (MonoImage *image, guint32 token)
12349 int index = mono_metadata_declsec_from_index (image, token);
12350 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12351 guint32 result = 0;
12355 /* HasSecurity can be present for other, not specially encoded, attributes,
12356 e.g. SuppressUnmanagedCodeSecurityAttribute */
12360 for (i = index; i < t->rows; i++) {
12361 guint32 cols [MONO_DECL_SECURITY_SIZE];
12363 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12364 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12367 action = cols [MONO_DECL_SECURITY_ACTION];
12368 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12369 result |= declsec_flags_map [action];
12371 g_assert_not_reached ();
12378 * Get the security actions (in the form of flags) associated with the specified method.
12380 * @method: The method for which we want the declarative security flags.
12381 * Return the declarative security flags for the method (only).
12383 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12384 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12387 mono_declsec_flags_from_method (MonoMethod *method)
12389 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12390 /* FIXME: No cache (for the moment) */
12391 guint32 idx = mono_method_get_index (method);
12392 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12393 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12394 return mono_declsec_get_flags (method->klass->image, idx);
12400 * Get the security actions (in the form of flags) associated with the specified class.
12402 * @klass: The class for which we want the declarative security flags.
12403 * Return the declarative security flags for the class.
12405 * Note: We cache the flags inside the MonoClass structure as this will get
12406 * called very often (at least for each method).
12409 mono_declsec_flags_from_class (MonoClass *klass)
12411 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12412 if (!klass->ext || !klass->ext->declsec_flags) {
12415 idx = mono_metadata_token_index (klass->type_token);
12416 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12417 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12418 mono_loader_lock ();
12419 mono_class_alloc_ext (klass);
12420 mono_loader_unlock ();
12421 /* we cache the flags on classes */
12422 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12424 return klass->ext->declsec_flags;
12430 * Get the security actions (in the form of flags) associated with the specified assembly.
12432 * @assembly: The assembly for which we want the declarative security flags.
12433 * Return the declarative security flags for the assembly.
12436 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12438 guint32 idx = 1; /* there is only one assembly */
12439 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12440 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12441 return mono_declsec_get_flags (assembly->image, idx);
12446 * Fill actions for the specific index (which may either be an encoded class token or
12447 * an encoded method token) from the metadata image.
12448 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12451 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12452 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12454 MonoBoolean result = FALSE;
12456 guint32 cols [MONO_DECL_SECURITY_SIZE];
12457 int index = mono_metadata_declsec_from_index (image, token);
12460 t = &image->tables [MONO_TABLE_DECLSECURITY];
12461 for (i = index; i < t->rows; i++) {
12462 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12464 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12467 /* if present only replace (class) permissions with method permissions */
12468 /* if empty accept either class or method permissions */
12469 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12470 if (!actions->demand.blob) {
12471 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12472 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12473 actions->demand.blob = (char*) (blob + 2);
12474 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12477 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12478 if (!actions->noncasdemand.blob) {
12479 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12480 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12481 actions->noncasdemand.blob = (char*) (blob + 2);
12482 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12485 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12486 if (!actions->demandchoice.blob) {
12487 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12488 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12489 actions->demandchoice.blob = (char*) (blob + 2);
12490 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12500 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12501 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12503 guint32 idx = mono_metadata_token_index (klass->type_token);
12504 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12505 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12506 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12510 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12511 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12513 guint32 idx = mono_method_get_index (method);
12514 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12515 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12516 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12520 * Collect all actions (that requires to generate code in mini) assigned for
12521 * the specified method.
12522 * Note: Don't use the content of actions if the function return FALSE.
12525 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12527 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12528 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12529 MonoBoolean result = FALSE;
12532 /* quick exit if no declarative security is present in the metadata */
12533 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12536 /* we want the original as the wrapper is "free" of the security informations */
12537 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12538 method = mono_marshal_method_from_wrapper (method);
12543 /* First we look for method-level attributes */
12544 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12545 mono_class_init (method->klass);
12546 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12548 result = mono_declsec_get_method_demands_params (method, demands,
12549 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12552 /* Here we use (or create) the class declarative cache to look for demands */
12553 flags = mono_declsec_flags_from_class (method->klass);
12554 if (flags & mask) {
12556 mono_class_init (method->klass);
12557 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12559 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12560 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12563 /* The boolean return value is used as a shortcut in case nothing needs to
12564 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12570 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12572 * Note: Don't use the content of actions if the function return FALSE.
12575 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12577 MonoBoolean result = FALSE;
12580 /* quick exit if no declarative security is present in the metadata */
12581 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12584 /* we want the original as the wrapper is "free" of the security informations */
12585 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12586 method = mono_marshal_method_from_wrapper (method);
12591 /* results are independant - zeroize both */
12592 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12593 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12595 /* First we look for method-level attributes */
12596 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12597 mono_class_init (method->klass);
12599 result = mono_declsec_get_method_demands_params (method, cmethod,
12600 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12603 /* Here we use (or create) the class declarative cache to look for demands */
12604 flags = mono_declsec_flags_from_class (method->klass);
12605 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12606 mono_class_init (method->klass);
12608 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12609 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12616 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12618 * @klass The inherited class - this is the class that provides the security check (attributes)
12620 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12622 * Note: Don't use the content of actions if the function return FALSE.
12625 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12627 MonoBoolean result = FALSE;
12630 /* quick exit if no declarative security is present in the metadata */
12631 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12634 /* Here we use (or create) the class declarative cache to look for demands */
12635 flags = mono_declsec_flags_from_class (klass);
12636 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12637 mono_class_init (klass);
12638 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12640 result |= mono_declsec_get_class_demands_params (klass, demands,
12641 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12648 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12650 * Note: Don't use the content of actions if the function return FALSE.
12653 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12655 /* quick exit if no declarative security is present in the metadata */
12656 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12659 /* we want the original as the wrapper is "free" of the security informations */
12660 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12661 method = mono_marshal_method_from_wrapper (method);
12666 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12667 mono_class_init (method->klass);
12668 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12670 return mono_declsec_get_method_demands_params (method, demands,
12671 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12678 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12680 guint32 cols [MONO_DECL_SECURITY_SIZE];
12684 int index = mono_metadata_declsec_from_index (image, token);
12688 t = &image->tables [MONO_TABLE_DECLSECURITY];
12689 for (i = index; i < t->rows; i++) {
12690 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12692 /* shortcut - index are ordered */
12693 if (token != cols [MONO_DECL_SECURITY_PARENT])
12696 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12697 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12698 entry->blob = (char*) (metadata + 2);
12699 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12708 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12710 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12711 guint32 idx = mono_method_get_index (method);
12712 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12713 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12714 return get_declsec_action (method->klass->image, idx, action, entry);
12720 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12723 guint32 flags = mono_declsec_flags_from_class (klass);
12724 if (declsec_flags_map [action] & flags) {
12725 guint32 idx = mono_metadata_token_index (klass->type_token);
12726 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12727 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12728 return get_declsec_action (klass->image, idx, action, entry);
12734 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12736 guint32 idx = 1; /* there is only one assembly */
12737 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12738 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12740 return get_declsec_action (assembly->image, idx, action, entry);
12744 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12746 MonoObject *res, *exc;
12748 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12749 static MonoMethod *method = NULL;
12751 if (!System_Reflection_Emit_TypeBuilder) {
12752 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12753 g_assert (System_Reflection_Emit_TypeBuilder);
12755 if (method == NULL) {
12756 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12761 * The result of mono_type_get_object () might be a System.MonoType but we
12762 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12764 g_assert (mono_class_get_ref_info (klass));
12765 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12767 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12769 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12773 return *(MonoBoolean*)mono_object_unbox (res);
12777 * mono_reflection_type_get_type:
12778 * @reftype: the System.Type object
12780 * Returns the MonoType* associated with the C# System.Type object @reftype.
12783 mono_reflection_type_get_type (MonoReflectionType *reftype)
12785 g_assert (reftype);
12787 return mono_reflection_type_get_handle (reftype);